我正在解决这个问题:
考虑30:1,2,3,5,6,10,15,30的除数 可以看出,对于每个除数d为30,d + 30 / d为素数。
求出所有正整数n的总和不超过100 000 000 这样,对于n的每个除数d,d + n / d是素数。
我确信我已经拥有它,但是唉,这显然给了我错误的答案(12094504411074
)。
我很确定我对Eratosthenes的筛子正在工作(但可能没有),所以我认为问题出在算法的某个地方。它似乎得到n = 30
的正确答案(1+2+6+10+22+30 = 71
- 这是正确的吗?),但随着数字变大,它显然停止工作。
这是我的Java代码:
import java.util.HashSet;
public class Generators {
static HashSet<Integer> hSet = new HashSet<Integer>();
public static void main(String[] args) {
// TODO Auto-generated method stub
int n = 100000000;
sieveErat(n + 1); //Fill a hashSet with prime numbers
System.out.println("Sieve complete");
int check = 0;
long sum = 3;
for(int i = 2; i <= n; i++){
int numDivisors = 0;
int numPrimeChecks = 0;
boolean done = false;
if(!hSet.contains(i+1)){ //i+1 must be a prime number for i to be prime generating
continue;
}
else{
for(int j = 2; j < i/2; j++){
if(i%j == 0){
numDivisors++;
check = j + i/j;
if(hSet.contains(check)){
done = true;
numPrimeChecks++;
}
}else{
break;
}
}
if(numPrimeChecks == numDivisors && done){
sum += i;
}
}
}
System.out.println(sum);
}
public static void sieveErat(int N){
boolean[] isPrime = new boolean[N + 1];
for (int i = 2; i <= N; i++) {
isPrime[i] = true;
//count++;
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i*i <= N; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime[i]) {
for (int j = i; i*j <= N; j++) {
isPrime[i*j] = false;
// count--;
}
}
}
for(int i = 2; i < isPrime.length; i++){
if(isPrime[i]){
hSet.add(i);
}
}
// System.out.println(count);
}
}
答案 0 :(得分:1)
你筛子的数学对我来说很好看。我把它砍掉来使用BitSet,它更节省空间。 5761455
素数低于100,000,000是否正确?
一旦我的代码正常工作,我得到了相同的数字(12094504411075
)应该得到什么?
我认为这有点不对(为了清晰起见,我更改了变量名称以匹配问题)
for(int d = 2; d < Math.sqrt(n+3); d++) {
if (n % d == 0) {
numDivisors++;
int check = d + n / d;
if (primes.get(check)) {
// **** What does done mean??? ****
//done = true;
numPrimeChecks++;
} else {
// **** Added! Got a divisor that did not check. No point in going on.
break;
}
} else {
// **** Why break here??? ****
//break;
}
}
NB 我已编辑此代码以反映我们最终认定的正确解决方案。
为什么在您点击不d
d
的{{1}}时,您会突然离开n
圈?肯定是不对的。
但是,当你有一个不检查的除数时,我认为你可以突破d
循环。
此外,您done
的预期功能是什么?它似乎没有实际功能。
而且,为什么要在sum
开始3
?
删除break
我现在获得值1739023853139
。这是对的吗?
<强>加强>
这是我的筛子。与您的相同,但构建BitSet
,在这种情况下,结构比HashSet
更有效:
public static BitSet sieveOfEratosthenes(int n) {
BitSet isPrime = new BitSet(n);
// Iniially all numbers are prime.
for (int i = 2; i <= n; i++) {
isPrime.set(i);
}
// mark non-primes <= N using Sieve of Eratosthenes
for (int i = 2; i * i <= n; i++) {
// if i is prime, then mark multiples of i as nonprime
// suffices to consider mutiples i, i+1, ..., N/i
if (isPrime.get(i)) {
for (int j = i; i * j <= n; j++) {
isPrime.clear(i * j);
}
}
}
//System.out.println("Found " + isPrime.cardinality() + " primes");
return isPrime;
}