Я снова развлекаюсь с проблемами Project Euler, и я заметил, что мое решение для числа 12 является одним из моих самых медленных в ~593.275 ms
за прохождение. Это второе решение для числа 10 при ~1254.593 ms
за прохождение. Все мои другие ответы занимают меньше 3 ms
, чтобы работать с наилучшим образом в 1 ms
.
Мое решение Java для Проблема 12:
Основной():
int index = 1;
long currTriangleNum = 1;
while (numDivisors(currTriangleNum) <= 500) {
index++;
currTriangleNum += index;
}
System.out.println(currTriangleNum);
numDivisors():
public static int numDivisors(long num) {
int numTotal = 0;
if (num > 1)
if (num % 2 == 0) {
for (long i = 1; i * i <= num; i++)
if (num % i == 0)
numTotal+=2;
} else {
// halves the time for odd numbers
for (long i = 1; i * i <= num; i+=2)
if (num % i == 0)
numTotal+=2;
}
else if (num == 0)
return 0;
else if (num == 1)
return 1;
else (num < 0)
return numDivisors(num *= -1);
return numTotal;
}
.
Оглядываясь на форум решений, некоторые люди обнаружили, что эти формулы (n = (p ^ a) (q ^ b) (r ^ c)... и d (n) = (a + 1) (b + 1) (c + 1)...) работал для них, но лично я не вижу, как это будет быстрее; возможно, быстрее, но не в программе.
.
Основной мыслительный процесс выглядит следующим образом:
Мы хотим рассчитать число делителей в 48. Посмотрев на дерево факторов ниже, мы можем заключить, что 48 = (2^4)(3^1)
[n = (p ^ a) (q ^ b) (r ^ c)... ].
48
/ \
2 24
/ \
2 12
/ \
2 06
/ \
2 3
Зная это, мы строим формулу d(48) = (4+1)(1+1)
[d (n) = (a + 1) (b + 1) (c + 1)...], чтобы определить, что 48 имеет 10 факторов.
d(n) = (a+1)(b+1)(c+1)...
d(48) = (4+1)(1+1)
d(48) = (5)(2)
d(48) = 10
.
Как я могу оптимизировать свой код? Являются ли эти формулы лучшим решением? Я считаю, что найти все основные факторы, а затем реализовать формулы займет больше времени, чем программа, которую я уже имел.
Большое спасибо,
Жюстьян
EDIT:
Прежде чем кто-нибудь начнет размещать ссылки, я просмотрел похожие вопросы в SO без везения - я просто не могу придумать реализации своих методов, которые будут работать быстрее, чем то, что у меня уже есть.
EDIT2:
Моя вторая попытка на сите Эратосфена (для задачи 10):
int p = 3, n = 2000000;
long total = 0;
boolean[] sieve = new boolean[n];
for (int i = 3; i < n; i += 2)
sieve[i] = true;
sieve[2] = true;
while (p * p < n) {
for (int i = p; i < n; i++)
if (sieve[i] && (i % p) == 0)
sieve[i] = false;
p++;
while (!sieve[p])
p++;
}
for (int i = 0; i < n; i++)
if (sieve[i])
total += i;
System.out.println(total);
Работает в ~985.399 ms
- не намного быстрее, чем другой метод, но пока не оптимизирован. Он работает, однако.