Java 8: 1.8e8 2.4e8
Entri ini tidak dibandingkan dengan beberapa entri lain yang sudah ada, tetapi saya ingin memposting jawaban saya karena saya senang mengerjakannya.
Optimalisasi utama dari pendekatan saya adalah sebagai berikut:
- Setiap bilangan genap memiliki faktor terkecil 2, sehingga ini dapat ditambahkan secara gratis setelah setiap bilangan ganjil diproses. Pada dasarnya, jika Anda telah melakukan pekerjaan untuk menghitung
T(N)
kapan N % 2 == 1
, Anda tahu ituT(N + 1) == T(N) + 2
. Ini memungkinkan saya untuk mulai menghitung pada tiga dan meningkat dengan iterasi oleh dua atau dua.
- Saya menyimpan bilangan prima saya dalam sebuah array, bukan
Collection
tipe. Ini lebih dari dua kali lipat yang N
bisa saya jangkau.
- Saya menggunakan bilangan prima untuk faktor bilangan sebagai lawan melakukan Saringan Eratosthenes. Ini berarti bahwa penyimpanan memori saya terbatas hampir sepenuhnya ke array primes saya.
- Saya menyimpan akar kuadrat dari angka yang saya coba cari faktor terkecil. Saya mencoba pendekatan @ user1354678 dengan mengkuadratkan faktor prima setiap kali, tetapi ini menghabiskan sekitar 1e7 dari skor saya.
Itu semua yang ada untuk itu. Kode saya beralih dari 3 ke dua oleh dua hingga mendeteksi bahwa ia telah mencapai atau melebihi batas waktu, pada saat itu ia mengeluarkan jawabannya.
package sum_of_smallest_factors;
public final class SumOfSmallestFactors {
private static class Result {
private final int number;
int getNumber() {
return number;
}
private final long sum;
long getSum() {
return sum;
}
Result(int number, long sum) {
this.number = number;
this.sum = sum;
}
}
private static final long TIME_LIMIT = 60_000_000_000L; // 60 seconds x 1e9 nanoseconds / second
public static void main(String[] args) {
SumOfSmallestFactors main = new SumOfSmallestFactors();
Result result = main.run();
int number = result.getNumber();
long sum = result.getSum();
System.out.format("T(%,d) = %,d\n", number, sum);
}
private int[] primes = new int[16_777_216];
private int primeCount = 0;
private long startTime;
private SumOfSmallestFactors() {}
private Result run() {
startClock();
int number;
long sumOfSmallestFactors = 2;
for (number = 3; mayContinue(); number += 2) {
int smallestFactor = getSmallestFactor(number);
if (smallestFactor == number) {
addPrime(number);
}
sumOfSmallestFactors += smallestFactor + 2;
}
--number;
Result result = new Result(number, sumOfSmallestFactors);
return result;
}
private void startClock() {
startTime = System.nanoTime();
}
private boolean mayContinue() {
long currentTime = System.nanoTime();
long elapsedTime = currentTime - startTime;
boolean result = (elapsedTime < TIME_LIMIT);
return result;
}
private int getSmallestFactor(int number) {
int smallestFactor = number;
int squareRoot = (int) Math.ceil(Math.sqrt(number));
int index;
int prime = 3;
for (index = 0; index < primeCount; ++index) {
prime = primes[index];
if (prime > squareRoot) {
break;
}
int remainder = number % prime;
if (remainder == 0) {
smallestFactor = prime;
break;
}
}
return smallestFactor;
}
private void addPrime(int prime) {
primes[primeCount] = prime;
++primeCount;
}
}
Berjalan pada sistem yang berbeda (Windows 8.1, Intel core i7 @ 2.5 GHz, 8 GB RAM) dengan Java 8 versi terbaru memiliki hasil yang jauh lebih baik tanpa perubahan kode:
T(240,308,208) = 1,537,216,753,010,879