簡體   English   中英

優化的Eratosthenes篩的兩個數之間的質數總和

[英]Sum of Primes between two number from Optimized Sieve of Eratosthenes

這是我編寫的代碼,它為我提供nm之間的質數之和。

class TestClass {
    final static int MAX=1000000;
    final static boolean[] isPrime=isPrime();
    public static void main(String args[] ) throws Exception {
        BufferedReader keyboard= new BufferedReader(new InputStreamReader(System.in));
        int t=Integer.parseInt(keyboard.readLine());

        while(t>0 && t<=100){
            String[] tempInt=keyboard.readLine().split(" ");
            int n=Integer.parseInt(tempInt[0]);
            int m=Integer.parseInt(tempInt[1]);

            int sum=primeSum(n,m);
            System.out.println(sum);
            t--;
        }
    }

private static int primeSum(int n, int m) {
        int sum=0;

        for(int i=n;i<=m;i++){
            if(isPrime[i]){
                sum=sum+i;
            }
        }
        return sum;
    }

    private static boolean[] isPrime(){
        int maxFactor= (int)Math.sqrt(MAX);
        boolean[] isPrime=new boolean[MAX + 1];
        int len=isPrime.length;
        Arrays.fill(isPrime,true);
        isPrime[0]=false;
        isPrime[1]=false;
        for(int i=0;i<=maxFactor;i++){
            if(isPrime[i]){
                for(int j=i+i;j<len;j+=i){
                    isPrime[j]=false;
                }
            }
        }
        return isPrime;

    }

}

輸入:

2
1 99999
10000 99999

輸出:

454396537
448660141

現在,我嘗試通過僅采用通常在實踐中使用的奇數進一步優化篩分 這是我寫的優化篩功能

private static boolean[] isPrime(){
        int root=(int) Math.sqrt(MAX)+1;
        int limit=(MAX-1)/2;
        boolean[] isPrime=new boolean[limit];
        Arrays.fill(isPrime, true);
        root = root/2 -1;
        for(int i = 0; i < root ; i++){
            if(isPrime[i]){
                for( int j = 2*i*(i+3)+3 , p = 2*i+3; j < limit ; j=j+p ){
                    isPrime[j]=false;
                }
            }
        }

    return isPrime;
}

我能夠做到的。 我測試了上述功能,直到MAX=100為止。 這是Ideone Link IDEONE LINK測試結果

    truetruetruefalsetruetruefalsetruetruefalsetruefalsefalsetruetruefalsefalsetrue
falsetruetruefalsetruefalsefalsetruefalsefalsetruetruefalsefalsetruefalse
truetruefalsefalsetruefalsetruefalsefalsetruefalsefalsefalsetruefalse

即3 5 7 9̶11 13 1̶5̶17 19̶2̶1̶23 2̶5̶2̶7̶29 31̶3̶3̶̶3̶5̶37 3̶9̶等。

現在真正困擾我的是我在primeSum() method為優化過的篩子所做的索引primeSum() method

private static int primeSum(int n, int m) {
        int sum;
        if(n>0 && n<=2){
            sum=2;
        }else
            sum=0;
        //System.out.println(sum);
        for( int i = (n-3)/2; i <= (m-3)/2 ; i++){
            if(isPrime[i]){
                //System.out.println(i);
                sum=sum+2*i+3;
            }
        }
        return sum;
    }

但顯而易見, n索引在n<3失敗。 所以我必須這樣做才能使此代碼正常工作

if(n>0 && n<=2){
            sum=2;
            n=n+2;
        }

但是,當我必須在范圍之間找到它時,它仍然失敗

1 2
1 1
2 2

所以我應該再次包括這些情況並分別處理嗎?, iprimeSum()方法中對i進行索引的方法是否正確? 還是我能以更好的方式完成它? 還有什么其他可能的索引方式呢?

為什么不為nm之間的每個奇數循環:

private static int primeSum(int n, int m) {
    int sum = 0;
    if (n <= 2 && m >= 2)  // need this because 2 not in isPrime
        sum += 2;
    if (n%2 == 0)  // always start from an odd number
        n++;
    for (int i = n; i <= m; i += 2) {
        int index = (i - 3)/2;
        if (index >= 0 && isPrime[index]) {
            sum += i;
        }
    }
    return sum;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM