// Prob 2 Ваша проблема с biggesr сейчас ... Вы просто хотите узнать количество делителей?
Моим первым предложением будет до некоторой степени кэшировать ваш результат ... но это потенциально может потребовать вдвое большего объема памяти, чем у вас в начале: /.
Что вы можете сделать, это сгенерировать список простых чисел заранее ( с использованием алгоритма сита ). Идеально будет знать наибольшее число N
в вашем списке и генерировать все простые числа до его квадратного корня. Теперь для каждого числа в вашем списке вы хотите найти его представление как произведение факторов, т.е.
n = a1^p1 * a1^p2 *... *an^pn
Тогда сумма делителей будет.
((a1^(p1+1) - 1)/(a1 - 1))*((a2^(p2+1) - 1)/(a2-1))*...*((an^(pn+1) - 1)/(an-1))
Чтобы понять, что у вас есть (для n = 8) 1+ 2 + 4 + 8 = 15 = (16 - 1)/(2 - 1)
Это значительно улучшит скорость, но целочисленная факторизация (то, что вы действительно делаете) действительно дорогая ...
Редактировать:
В вашей ссылке максимум 5000000, поэтому у вас есть максимум 700 простых чисел
Простой алгоритм декомпозиции
void primedecomp(int number, const int* primetable, int* primecount,
int pos,int tablelen){
while(pos < tablelen && number % primetable[pos] !=0 )
pos++;
if(pos == tablelen)
return
while(number % primetable[pos] ==0 ){
number = number / primetable[pos];
primecount[pos]++;
}
//number has been modified
//too lazy to write a loop, so recursive call
primedecomp(number,primetable,primecount, pos+1,tablelen);
}
РЕДАКТИРОВАТЬ : вместо подсчета вычислите a^(n+1)
, используя primepow = a; primepow = a*primepow;
Это будет намного чище в C ++ или Java, где у вас есть hashmap. В конце
primecount
содержит значения pi
, о которых я говорил выше.
Даже если это выглядит страшно, вы создадите primetable
только один раз. Теперь этот алгоритм
запустить в худшем случае в O(tablelen)
, что составляет O(square root(Nmax))
. ваш начальный
цикл прошел в O(Nmax)
.