QSS: точное ускоренное вычисление суммы произведений целочисленных частных.
Quotient-Split Summation
Аннотация. Рассматривается задача точного вычисления арифметической суммы произведений целочисленных частных G(N) = sum(floor(N/k) floor(N/(2k+1))) для положительного целого параметра N. Предлагается и исследуется реализация QSS (Quotient-Split Summation), объединяющая прямое вычисление начального участка с группировкой индексов по одинаковому значению первого целочисленного частного. Для каждого такого блока доказывается, что второй частный принимает не более двух различных значений, что позволяет вычислять вклад блока несколькими арифметическими операциями. Алгоритм имеет O(sqrt(N)) итераций в стандартной модели подсчёта арифметических операций и возвращает точный целочисленный результат. В локальных измерениях на Python QSS оказался примерно в 27,57-2406,83 раза быстрее прямого перебора для проверенных размеров N от 10^4 до 10^8. По сравнению с двумя альтернативными реализациями группировки частных измеренное преимущество составило приблизительно 1,67-2,01 раза. Результаты относятся к конкретным реализациям и конфигурации компьютера и сами по себе не доказывают превосходства над всеми существующими алгоритмами.
1. Введение
Целочисленные частные вида floor(N/k) часто встречаются в задачах теории чисел, комбинаторики и вычислительной математики
[1]. При изменении k значение такого частного меняется ступенчато: множество соседних индексов может соответствовать одному и тому же результату целочисленного деления. Использование этих интервалов позволяет заменять многократные вычисления одинаковых величин обработкой целых блоков.
Методы группировки частных и суммирования по интервалам имеют известные применения. В частности, алгоритмы вычисления сумм floor-функций и метод Дирихле для суммирования арифметических функций используют связанные идеи разбиения диапазона и преобразования суммы
[2]. Однако рассматриваемая ниже сумма содержит произведение двух частных с разными знаменателями, floor(N/k) и floor(N/(2k+1)), поэтому для эффективного вычисления необходимо учитывать изменения обоих множителей.
Цель настоящей работы - описать и проверить конкретную реализацию QSS, определить её точность и асимптотическую сложность, а также сравнить время её выполнения с прямым суммированием и несколькими вариантами группировки.
2. Постановка задачи
Для целого N >= 1 требуется вычислить сумму
| G(N) = sumk=1N floor(N/k) floor(N/(2k+1)). |
(1) |
Здесь floor(x) обозначает наибольшее целое число, не превосходящее x. Все операции выполняются над целыми числами; приближения с плавающей точкой не используются для вычисления самой суммы.
Прямой алгоритм вычисляет оба частных для каждого k от 1 до N. Его количество итераций линейно по N. Для больших N это приводит к избыточным вычислениям, поскольку первый частный floor(N/k) принимает лишь O(sqrt(N)) различных положительных значений. Для смежной задачи точного суммирования целочисленных частных линейной функции см. документацию AtCoder Library
[3]. QSS использует это свойство и дополнительно учитывает поведение второго частного внутри каждого блока.
3. Основная идея QSS
Пусть s = floor(sqrt(N)). Алгоритм разделяет исходную сумму на две части:
| G(N) = sumk=1s floor(N/k) floor(N/(2k+1)) + sumk=s+1N floor(N/k) floor(N/(2k+1)). |
(2) |
Первую часть QSS вычисляет прямым циклом. Во второй части индексы группируются по значению a = floor(N/k). Для фиксированного положительного a соответствующий интервал имеет вид
| l = floor(N/(a+1)) + 1, r = floor(N/a). |
(3) |
Обозначим левую границу текущего блока через l, а правую через r. На всём блоке floor(N/k) = a, поэтому вклад блока равен
| V = a * sumk=lr floor(N/(2k+1)). |
(4) |
Ключевая особенность QSS заключается в том, что для рассматриваемых блоков второй частный принимает не более двух последовательных значений. Это позволяет вычислить сумму внутри блока без перебора всех его элементов.
4. Лемма об изменении второго частного
Рассмотрим блок с постоянным первым частным a, где 1 <= a <= floor(sqrt(N)). Его границы заданы формулой (3). Докажем, что разность вещественных значений N/(2l+1) и N/(2r+1) меньше единицы.
Из определения границ следует l > N/(a+1) и r > N/a - 1. Поэтому 2l+1 > 2N/(a+1), а 2r+1 >= N/a при N/a >= 1. Кроме того, r-l < N/(a(a+1)). Следовательно, получаем оценку
| 0 <= N/(2l+1) - N/(2r+1) < 2N(r-l)/((2l+1)(2r+1)) < 1. |
(5) |
Выходит, что вещественное значение N/(2k+1) на всём блоке изменяется менее чем на единицу. Поскольку эта функция монотонно убывает, её целая часть может принимать на блоке не более двух последовательных значений.
Обозначим b = floor(N/(2l+1)), c = floor(N/(2r+1)). Тогда
Лемма обосновывает возможность обработать каждый блок с помощью одного или двух постоянных значений второго множителя.
5. Вычисление вклада блока
Если b = c, оба частных постоянны на всём блоке. Тогда вклад равен
| V = (r - l + 1) * a * b. |
(7) |
Если b != c, второй частный принимает значение b в начале блока и значение c в его конце. Последний индекс, для которого floor(N/(2k+1)) = b, вычисляется по формуле
| q = floor((floor(N/b) - 1)/2). |
(8) |
Следовательно, индексы от l до q дают вклад a * (q-l+1) * b, а индексы от q+1 до r дают вклад a * (r-q) * c. Общий вклад равен
| V = a * ((q-l+1) * b + (r-q) * c). |
(9) |
После обработки блока алгоритм переходит к следующему значению a, уменьшая его на единицу. Границы блоков определяются целочисленным делением, поэтому интервалы не пересекаются и не пропускают индексы второй части суммы.
6. Псевдокод и оценка сложности
Алгоритм состоит из следующих шагов:
1. Вычислить s = floor(sqrt(N)).
2. Для k от 1 до s добавить к результату произведение двух частных.
3. Вычислить a_start = floor(N/(s+1)) и определить левую границу первого блока.
4. Для каждого a от a_start до 1 вычислить r = floor(N/a), значения второго частного на границах блока и вклад блока по формуле (7) или (9).
5. Вернуть полученную целую сумму.
Первая часть содержит не более floor(sqrt(N)) итераций. Во второй части a_start <= floor(sqrt(N)), поскольку N < (s+1)2. Следовательно, число блоков второй части также не превышает floor(sqrt(N)). На обработку каждого блока требуется постоянное число арифметических операций.
Эта оценка относится к числу арифметических операций в стандартной модели. В реальном Python стоимость целочисленных делений и операций с большими целыми числами зависит от размера операндов, поэтому оценка O(sqrt(N)) не означает, что фактическое время выполнения пропорционально ровно sqrt(N) с постоянным коэффициентом.
7. Проверка точности
Корректность реализации проверялась сравнением QSS с прямым вычислением исходной суммы и с альтернативными алгоритмами. Во всех проверках использовалось точное целочисленное равенство результатов.
| Проверка |
Результат |
| Все N от 1 до 5000 | Пройдена |
| Сравнение с Direct | Совпадение |
| Сравнение с Group-A | Совпадение |
| Сравнение с Joint | Совпадение |
| Сравнение с Swapped | Совпадение |
Для N = 100000000 ранее получено точное значение G(N) = 6137055069634959. Проверки подтверждают корректность исследованной реализации на протестированных значениях. Они не заменяют доказательства, приведённого в разделах 4 и 5, и не являются проверкой всех возможных значений N.
8. Экспериментальная методика
Сравнение проводилось на одном локальном компьютере с использованием Python 3. Для каждого метода выполнялись семь измерений времени; в таблице приведена медиана. Перед измерениями выполнялся предварительный запуск функции. Время указано в миллисекундах.
Сравнивались пять реализаций:
Direct - прямое суммирование всех N слагаемых.
Group-A - группировка по первому частному с перебором элементов внутри каждого блока.
Joint - совместная группировка по интервалам, где оба частных постоянны.
Swapped - альтернативный порядок группирования, начинающий со второго частного.
QSS - исследуемый гибридный алгоритм с прямым начальным участком и аналитической обработкой блоков.
Измерения относятся к конкретным реализациям, параметрам тестирования и конфигурации системы. Для другого компьютера, версии Python или фоновой нагрузки значения могут отличаться.
9. Результаты сравнительных измерений
| N |
QSS, мс |
Direct / QSS |
Group-A / QSS |
Joint / QSS |
Swapped / QSS |
| 10 000 |
0,0196 |
27,57x |
25,25x |
1,97x |
1,94x |
| 100 000 |
0,0733 |
75,75x |
69,44x |
1,93x |
1,86x |
| 1 000 000 |
0,2376 |
267,75x |
219,29x |
2,01x |
1,83x |
| 10 000 000 |
0,8234 |
778,38x |
660,89x |
1,73x |
1,67x |
| 100 000 000 |
2,5737 |
2406,83x |
2130,70x |
1,90x |
1,82x |
Отношение времени конкурирующего метода ко времени QSS вычисляется как Tcompetitor/TQSS. Значение больше единицы означает, что QSS быстрее соответствующей реализации.
Во всех пяти измеренных масштабах QSS показал наименьшее время среди сравниваемых реализаций. На N = 100000000 прямой алгоритм выполнялся приблизительно в 2407 раз дольше QSS, а реализация Group-A - приблизительно в 2131 раз дольше. Преимущество относительно Joint и Swapped было существенно меньше и находилось в диапазоне примерно 1,67-2,01 раза.
Различие между двумя группами сравнений объясняется прежде всего асимптотикой. Direct и Group-A сохраняют линейный по N перебор элементов. QSS обрабатывает O(sqrt(N)) индексов и блоков. Joint и Swapped уже используют группирование частных, поэтому преимущество QSS над ними связано главным образом с конкретной организацией вычислений и меньшими накладными расходами в исследованных реализациях.
10. Обсуждение результатов и ограничения
Эксперименты подтверждают практическую эффективность QSS для рассматриваемой суммы. Наибольший выигрыш наблюдается относительно прямого суммирования, где число обрабатываемых индексов сокращается с N до порядка sqrt(N). По сравнению с другими алгоритмами группирования преимущество меньше, поскольку они также избегают полного линейного перебора.
При этом следует различать три утверждения. Во-первых, точность алгоритма обоснована разбиением исходного диапазона на непересекающиеся блоки и леммой о двух возможных значениях второго частного. Во-вторых, сложность O(sqrt(N)) относится к количеству арифметических операций в стандартной модели. В-третьих, численные ускорения получены экспериментально и относятся к конкретным программным реализациям.
Перспективными направлениями дальнейшего исследования являются поиск более компактного аналитического выражения для вклада блоков, исследование дополнительных свойств суммы, проверка на существенно больших значениях N и сравнение с независимыми реализациями на нескольких системах. Отдельная задача - установить, существует ли преобразование, позволяющее уменьшить число арифметических операций ниже порядка sqrt(N).
11. Исходный код и воспроизводимость
Исходный код и скрипт сравнительных измерений доступны в репозитории
QSS. Для воспроизведения эксперимента следует загрузить файлы репозитория и запустить скрипт сравнительных измерений.
Для воспроизведения требуется Python 3. Запустите команду python benchmark.py из каталога с файлами. Скрипт проверяет совпадение результатов на малых значениях N, выполняет сравнительные измерения и выводит ускорение QSS относительно остальных реализаций.
12. Заключение
В работе рассмотрен алгоритм QSS (Quotient-Split Summation), обеспечивающий точное вычисление суммы произведений целочисленных частных G(N). Алгоритм сочетает прямой расчёт начального участка с группировкой по значениям первого частного. Для каждого последующего блока доказывается, что второй частный принимает не более двух последовательных значений, поэтому вклад блока вычисляется за постоянное число арифметических операций.
В стандартной модели подсчёта арифметических операций алгоритм выполняет O(sqrt(N)) шагов. Точность реализации проверена сравнением с альтернативными методами для всех N от 1 до 5000 и на дополнительных контрольных значениях. В проведённых локальных измерениях QSS оказался быстрее прямого перебора в 27,57-2406,83 раза, а по сравнению с двумя другими реализациями группировки - приблизительно в 1,67-2,01 раза.
По итогу, QSS является наиболее быстрым из пяти проверенных вариантов в проведённых экспериментах. Полученные результаты обосновывают его практическую эффективность для данной задачи, но не устанавливают абсолютного превосходства над всеми существующими алгоритмами и не доказывают новизну самой математической постановки.
Список использованных источников
1. Apostol T. M. Introduction to Analytic Number Theory. - New York : Springer-Verlag, 1976. — (Undergraduate Texts in Mathematics).
2. Dirichlet hyperbola method. - URL: https://en.wikipedia.org/wiki/Dirichlet_hyperbola_method (дата обращения: 10.10.2026).
3. AtCoder Library. Math — floor_sum. - URL: https://atcoder.github.io/ac-library/production/document_en/math.html (дата обращения: 10.10.2026).