Java 8: 1.8e8 2.4e8
Mục này không so sánh với một vài trong số những mục khác đã có, nhưng tôi muốn đăng câu trả lời của mình vì tôi rất vui khi làm việc này.
Các tối ưu hóa chính của phương pháp của tôi là như sau:
- Mỗi số chẵn có hệ số nhỏ nhất là 2, vì vậy những số này có thể được thêm miễn phí sau mỗi số lẻ được xử lý. Về cơ bản, nếu bạn đã thực hiện công việc để tính toán
T(N)
khi nào N % 2 == 1
, bạn biết điều đó T(N + 1) == T(N) + 2
. Điều này cho phép tôi bắt đầu đếm ở ba và tăng dần theo số lần lặp.
- Tôi lưu trữ các số nguyên tố của mình trong một mảng trái ngược với một
Collection
loại. Điều này nhiều hơn gấp đôi N
tôi có thể đạt được.
- Tôi sử dụng các số nguyên tố để tính một số thay vì thực hiện Sàng của Eratosthenes. Điều này có nghĩa là bộ nhớ lưu trữ của tôi bị hạn chế gần như hoàn toàn với mảng số nguyên tố của tôi.
- Tôi lưu trữ căn bậc hai của số mà tôi đang cố gắng tìm yếu tố nhỏ nhất. Tôi đã thử cách tiếp cận bình phương của một người dùng @ user1354678, nhưng điều này làm tôi mất khoảng 1e7 từ điểm số của mình.
Đó là tất cả về nó. Mã của tôi lặp đi lặp lại từ 3 trở đi cho đến khi nó phát hiện ra rằng nó đã đạt hoặc vượt quá giới hạn thời gian, tại thời điểm đó, nó sẽ đưa ra câu trả lời.
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;
}
}
Chạy trên một hệ thống khác (Windows 8.1, Intel core i7 @ 2.5 GHz, RAM 8 GB) với phiên bản Java 8 mới nhất có kết quả tốt hơn rõ rệt mà không có thay đổi mã:
T(240,308,208) = 1,537,216,753,010,879