LightOJ1529(普通素数筛,埃拉特斯特尼筛法,欧拉筛法)

Goldbach's conjecture is one of the oldest unsolved problems in number theory and in all of mathematics. It states:

Every even integer, greater than 2, can be expressed as the sum of two primes [1].

Now your task is to check whether this conjecture holds for integers up to 107.

Input

Input starts with an integer T (≤ 300), denoting the number of test cases.

Each case starts with a line containing an integer n (4 ≤ n ≤ 107, n is even).

Output

For each case, print the case number and the number of ways you can express n as sum of two primes. To be more specific, we want to find the number of (a, b) where

1)      Both a and b are prime

2)      a + b = n

3)      a ≤ b

Sample Input

2

6

4

Sample Output

Case 1: 1

Case 2: 1

Note

1.      An integer is said to be prime, if it is divisible by exactly two different integers. First few primes are 2, 3, 5, 7, 11, 13, ...

 

感谢李大超叫我筛选法,呜呜呜uwuwuuwuwuwuwu、

先看素数的三种筛选法:

转载超大神的不加他的链接,就不加。。。

我怂了、、、
原文链接:https://blog.csdn.net/daoshen1314/article/details/100054514

1.最普通的方法不做赘述----按照素数的定义   时间复杂度O(n*n)

public class 普通的方法 {
   static final int max=100;
   static int prime[]=new int[max];
   public static void main(String[] args) {
      int k=0;
      for(int i=2;i<max;i++){
          boolean flag=true;
          for(int j=2;j<=Math.sqrt(i);j++)
              if(i%j==0)
                  flag=false;
          if(flag) prime[k++]=i;
    }
      
    for(int i=0;i<k;i++){
         System.out.println(prime[i]);
     }
}
}

2.埃拉特斯特尼筛法--当i为素数,i的倍数i*k都不是素数    时间复杂度O(nloglogn)

import java.util.Arrays;
 
public class 埃拉特斯特尼筛法 {
   static final int max=100;
   static boolean is_prime[]=new boolean[max];
   static int prime[]=new int[max];
   public static void main(String[] args) {
       Arrays.fill(is_prime, true);
       is_prime[0]=is_prime[1]=false;
       int k=0;
       for(int i=2;i<max;i++){
           if(is_prime[i]){
               prime[k++]=i;
               for(int j=2*i;j<max;j+=i){
                   is_prime[j]=false;
               }
           }
       }
       for(int i=0;i<k;i++){
           System.out.println(prime[i]);
       }
}
}

3.线性欧拉筛法--每个合数只被它的最小素因子筛选一次   时间复杂度O(n)\

import java.util.Arrays;
 
public class 线性欧拉筛法 {
    static final int max=100000;
    static boolean vis[]=new boolean[max];
    static int prime[]=new int[max];
    public static void main(String[] args) {
       Arrays.fill(vis, true);
       vis[0]=vis[1]=false;
       int k=0;
       for(int i=2;i<max;i++){
           if(vis[i])
               prime[k++]=i;
           for(int j=0;j<k&&i*prime[j]<max;j++){
               vis[i*prime[j]]=false;
               if(i%prime[j]==0){
                   break;
               }
           }
       }
       for(int i=0;i<k;i++){
           System.out.println(prime[i]);
       }
}
}

 vis[i*prime[j]]=false     把prime里记录的素数升序来当作消去合数的最小素因子

if(i%prime[j]==0) break;

      当i是prime[j]的倍数时,i=k*prime[j],如果继续进行j+1,i*prime[j+1]=prime[j]*(k*prime[j+1]),

      prime[j]是最小素因子,当i=k*prime[j+1]时,会重复,所以break

      eg:当i=8,j=0,prime[0]=2,如果不break,i*prime[j+1]=8*3=12*2,也就是说在i=12的时候也会筛这个合数

 


import java.util.Scanner;
import java.util.Arrays;
public class Main {
    static int inf=20000007;
    static boolean primes[]=new boolean[inf];
    static int p[]=new int[2000005];
    static int pn=0;
    static void prime(){
        pn=0;
        Arrays.fill(primes,false);
        
        primes[0]=primes[1]=true;
        for(int i=2;i<inf;i++){
            if(!primes[i])
                p[pn++]=i;
            for(int j=0;j<pn&&i*p[j]<inf;j++){
                    primes[i*p[j]]=true;
                    if(i%p[j]==0){
                        break;
                    }
                }
            
        }
    }
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Scanner sc=new Scanner(System.in);
        int N=sc.nextInt();
        int k=0;
        prime();
        for(int i=0;i<N;i++){
            int n=sc.nextInt();
            int ans=0;
            for(int j=0;p[j]<=n;j++){
                if(primes[n-p[j]]==false&&p[j]<=n-p[j]){
                    ans++;
                }
            }
            System.out.println("Case "+(i+1)+": "+ans);
        }
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值