首先,你必須使用一個精確的算術平均值。其他人建議使用BigInteger
。你可以這樣做。對我來說,這感覺有點像作弊(對於後來遇到更大整數的問題,這會更重要),所以更有趣的方式(imho)是自己編寫必要的任意精度操作。
其次,600851475143足夠小,可以用long
做到精確,這將更快。
第三,您的循環無法正確檢查素數因子。你只是檢查奇數。這是一個準系統(不完整)解決方案:
long num = 600851475143L;
List<Long> factors = new ArrayList<Long>(); // or use a Set
if (num & 1 == 0) {
factors.add(2L);
}
for (long i=3; i*i<=num; i+=2) {
// first check i is prime
// if i is prime check if it is a factor of num
}
檢查是否有素數具有不同的實現級別。最天真的:
public boolean isPrime(long num) {
for (long i=2; i<=num; i++) {
if (num % i == 0) {
return false;
}
}
return true;
}
當然這會做各種不必要的檢查。正如你已經確定你只需要檢查人數達到sqrt(n)
便可消除偶數(2以外):
public boolean isPrime(long num) {
if (num & 1 == 0) {
return false; // checks divisibility by 2
}
for (long i=3; i*i<=num; i+=2) {
if (num % i == 0) {
return false;
}
}
return true;
}
但是你可以做得比這更好。另一個優化是,您只需要在該範圍內檢查素數。 63的主要因素是3和7.如果一個數不能被3或7整除,那麼它的定義將不能被63整除。
所以你想要做的是建立可能是Set<Long>
或素數直到廣場等於或高於您的目標數量。然後,只需將這一系列數字整除到目標中即可。