Георгий Гуляев
3 июля 2026 г.
На сайте <https://projecteuler.net> опубликовано на данный момент более 1000 задач и эта коллекция со временем продолжает пополняться. Придумывают эти задачи математики со знаниями в области программирования. В большинстве своем это задачи из теории чисел или комбинаторики, но встречаются и другие темы.
Каждая задача имеет сложность в процентах от 0 до 40, в зависимости от того как быстро ее решают пользователи ресурса. Решение, как правило, требует написания некоторого небольшого кода на каком-либо языке программирования, но для более сложных задач одного программирования бывает недостаточно - требуются знания и умения в области математики.
Решив задачу (введя правильный численный ответ), пользователь получает доступ к закрытым материалам задачи и решениям других пользователей, а также может опубликовать свое решение. Авторы ресурса, естественно, не хотели бы, чтобы решения задач и ответы к ним публиковались где-либо еще. Разрешено только в целях обучения обсуждать идеи решения первых 100 задач.
Поэтому, в данной статье для демонстрации поиска решения задач такого рода, мы не будем использовать задачи ресурса [https://projecteuler.](https://projecteuler.net) [net](https://projecteuler.net), а рассмотрим свою оригинальную задачу.
Задача. На плоскости расположена прямоугольная таблица, в клетках которой записаны все натуральные числа снизу вверх по диагоналям в следующим порядке:
| y | |||||||||
|---|---|---|---|---|---|---|---|---|---|
| 8 | |||||||||
| 7 | 28 | ||||||||
| 6 | 21 | 27 | |||||||
| 5 | 15 | 20 | 26 | ||||||
| 4 | 10 | 14 | 19 | 25 | |||||
| 3 | 6 | 9 | 13 | 18 | 24 | ||||
| 2 | 3 | 5 | 8 | 12 | 17 | 23 | |||
| 1 | 1 | 2 | 4 | 7 | 11 | 16 | 22 | ||
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | X |
Определим функцию f(x, y) = числу в столбце x и строке y таблицы, тогда f(1, 1) = 1, f(2, 1) = 2, f(1, 2) = 3, f(2, 2) = 5, f(5, 3) = 24, ....
- Вычислить f(123456789, 987654321).
2. Определим функцию
$$s(n) = \sum_{x=1}^{n} \sum_{y=1}^{n} (f(x, y) - xy)$$
Можно проверить, что s(123)=75367635, s(123456)=77432320610578913280. Вычислить s(1234567890). В качестве ответа использовать 10 последних цифр результата вычисления.
Решение.
- Первое задание - относительно простое. Тут присутствуют чисто технические сложности при написании функции f(x,y). Если не применять никакой математики, то можно просто строить всю таблицу (x,y) до некоторого значения n и затем использовать ее для вычисления f(x,y). Программа на языке программирования Julia:
`` function table(n) 1 = [(1,1)] for i in 2:n (x,y) = 1[end] if x==1 x=y+1 y=1 push!(1,(x,y)) else x - = 1 y+=1 push!(1,(x,y)) end end 1 end ``
`` julia> l = table(28) 28-element Vector{Tuple{Int64, Int64}}: (1, 1) (2, 1) (1, 2) (3, 1) (2, 2) (1, 3) (4, 1) (3, 2) (2, 3) (1, 4) (5, 1) (4, 2) (3, 3) (2, 4) (1, 5) (6, 1) (5, 2) (4, 3) (3, 4) (2, 5) (1, 6) (7, 1) (6, 2) (5, 3) (4, 4) (3, 5) (2, 6) (1, 7) julia> l[25] (4, 4) ``
Тут мы вывели все координаты (x, y) для чисел от 1 до 28, например для 25 это (4, 4). Лучше, конечно, не строить таблицу в памяти, так как для больших n она будет занимать много места, а только пробегать по ней. Так появляется наша первая версия для функции f(x, y):
`` function f(x,y) i = 1; j = 1; r = 1 while i < x + y & j < x + y if i==x&&j==y return r end if i==1 i=j+1 j=1 else i-=1 j+=1 end r+=1 end end julia> f(3,4) 19 julia> f(4,4) 25 ``
Координаты (x,y) всегда попадают в квадрат со стороной менее x+y, поэтому действуют ограничения: i < x+y и j < x+y. Эта программа очень неэффективная, с ее помощью решить первую задачу мы не сможем:
`` julia> @time f(12345,54321) 2.457699 seconds 2222132101 ``
f(123456,654321) - уже дождаться невозможно.
Пришло время математики. Придется немного порассуждать, чтобы вывести общую формулу для f(x,y). В таблице на картинке в условии задачи возьмем какое-нибудь число в первом ряду, например 16. Количество чисел до него можно вычислить как сумму 1+2+3+4+5=15. Это
сумма арифметической прогрессии: $\frac{5(5+1)}{2}$ , таким образом $16=\frac{5(5+1)}{2}+1$ или $16=\frac{6(6-1)}{2}+1$ , учитывая, что 16 - шестое число в первом ряду. В общем случае $f(x,1)=\frac{x(x-1)}{2}+1$ . Теперь, для того чтобы получить формулу для f(x,y), рассмотрим частный случай:
$$f(x+y-1,1) = \frac{(x+y-1)(x+y-2)}{2} + 1$$
По построению таблицы, при b < a у нас справедлива формула f(a,b) = f(a-1,b+1)+1. Применяя ее y-1 раз к формуле для f(x+y-1,1), получаем
$$f(x,y) = \frac{(x+y-1)(x+y-2)}{2} + y$$
Теперь мы можем решить первую задачу без проблем:
- Теперь, когда у нас есть такая простая формула, кажется, что и со второй частью задачи у нас не будет проблем, но не тут то было. Функцию для вычисления суммы составить несложно:
`` function sm(n) f(x,y) = div((x+y-1)(x+y-2),2) + y s = Int128(0) for i in 1:n, j in 1:n s+=f(i,j)-ij end s\nend ``
Здесь мы накапливаем сумму в переменной типа Int128, так как при больших n она может превзойти Int64.
julia> sm(123) 75367635
julia> sm(12345) 7740880282734900
julia> @time sm(123456) 26.305627 seconds 77432320610578913280
Результаты вычисления sm(123) и sm(123456) совпали с приведенными в условии задачи, однако становится очевидным, что эта функция также недостаточно эффективна и не позволит нам за приемлемое время вычислить требуемое значение: sm(1234567890).
Опять обратимся к математике. Если существует возможность вычислить требуемую сумму быстрее, чем полный перебор всех слагаемых, то должно быть какое-то соотношение (формула, теорема), позволяющее вычислять такие суммы.
Прежде всего, заметим, что найденную формулу для f(x, y) можно немного видоизменить, раскрывая скобки:
$$f(x,y) = \frac{(x+y-1)(x+y-2)}{2} + y = \frac{(x+y-1)(x+y)-2(x+y-1))}{2} + y = \frac{(x+y)(x+y-1))}{2} - x + 1$$ то есть
$$f(x,y) = \frac{(x+y)(x+y-1)}{2} - x + 1$$
Обратим внимание на то, что в формуле присутствуют так называемые треугольные числа вида: Tn = n(n−1) 2 . Поиском в интернет находим следующие соотношения для них (смотри, например, статью из википедии [https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE) [D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5\\_%D1%87%D0%B8%D1%81%D0%](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE) [BB%D0%BE](https://ru.wikipedia.org/wiki/%D0%A2%D1%80%D0%B5%D1%83%D0%B3%D0%BE%D0%BB%D1%8C%D0%BD%D0%BE%D0%B5_%D1%87%D0%B8%D1%81%D0%BB%D0%BE)):
$$T_{n+m} = T_n + T_m + mn$$
$$T_1 + T_2 + T_3 + \ldots + T_n = 0 + 1 + 3 + 6 + \ldots + \frac{n(n-1)}{2} = \frac{n^3 - n}{6}$$
Таким образом, на основании первого равенства, формулу для f(x,y) можно переписать в виде:
$$f(x,y) = \frac{(x+y)(x+y-1)}{2} - x + 1 = T_{x+y} - x + 1 = T_x + T_y + xy - x + 1$$
Применяя теперь эту формулу для f(x,y) и второе равенство, получаем
$$s(n) = \sum_{x=1}^{n} \sum_{y=1}^{n} (f(x,y) - xy) = \sum_{x=1}^{n} \sum_{y=1}^{n} (T_x + T_y - x + 1) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + \frac{n^3 - n}{6} - nx + n) = \sum_{x=1}^{n} (nT_x + n) = \sum_{x=1}^{n} (nT_x + n) = \sum_{x=1}^{n} (nT_x + n) = \sum_{x=1}^{n} (nT_x + n) = \sum_{x=1}^{n}$$
$$n\frac{n^3 - n}{6} + n\frac{n^3 - n}{6} - n\frac{n(n+1)}{2} + n^2 = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} = \frac{2n(n^3 - n) - 3n^2(n+1) + 6n^2}{6} =$$
$$\frac{2n^4 - 2n^2 - 3n^3 - 3n^2 + 6n^2}{6} = \frac{n^2(2n^2 - 3n + 1)}{6} = \frac{n^2(2n - 1)(n - 1)}{6}$$
Таким образом, сумму s(n) можно вычислять, даже не зная всех ее слагаемых. Теперь, без проблем мгновенно получается требуемый результат:
$$sm(n) = div(n^2*(2*n-1)*(n-1),6)$$
julia> sm(123) 75367635
julia> sm(Int128(123456)) 77432320610578913280
julia> sm(Int128(1234567890)) 774352408386692628193094876226110850
Последние 10 цифр: 6226110850
Выводы. Для решения подобных задач бывает недостаточно умения просто программировать на каком-либо языке. Поиск эффективного алгоритма может потребовать от вас некоторых знаний в области математики и определенной математической культуры для проведения логических рассуждений и преобразований математических выражений.