Прежде всего, ваша формула неверна. Согласно вашей формуле, сумма делителей 12 должна быть 12. На самом деле это 28. Правильная формула (p<sub>1</sub><sup>a<sub>1</sub></sup> - 1)*(p<sub>2</sub><sup>a<sub>2</sub></sup> - 1) * ... * (p<sub>k</sub><sup>a<sub>k</sub></sup> - 1)/( (p<sub>1</sub> - 1) * (p<sub>2</sub> - 1) * ... * (p<sub>k</sub> - 1) )
.
Тем не менее, самый простой подход, вероятно, просто сделать сито. Можно сообразить со смещениями, но для простоты просто создайте массив из 2000 001 целых чисел от 0 до 2 миллионов. Инициализируйте это к 0s. Тогда:
for (ull i = 1; i < MAX; ++i) {
for (ull j = i; j < MAX; j += i) {
factors[j] += i;
}
}
Это может показаться неэффективным, но это не так уж плохо. Общее количество выполненных работ для чисел до N
составляет N + N/2 + N/3 + ... + N/N = O(N log(N))
, что на несколько порядков меньше, чем пробное деление. И все операции - сложение и сравнение, которые быстры для целых чисел.
Если вы хотите продолжить свою первоначальную идею и формулу, вы можете сделать это более эффективным, используя модифицированное сито Эратосфена, чтобы создать массив от 1 до 2 миллионов, перечисляющий главный фактор каждого числа. Построение этого массива происходит довольно быстро, и вы можете взять любое число и разложить его на множители, гораздо быстрее, чем с пробным делением.