素数与求解方法

素数是只能被1和自身整除的数。本文介绍了素数的重要性,如歌德巴赫猜想和孪生素数猜想,并展示了不同求解素数的算法,包括暴力求解和筛选法,如一次筛选和二次筛选,以及它们的时间和空间复杂度分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    素数指的是一个只能被1和它本身整除的数,它是一个在数论中占重要研究地位的数,是一个数学皇冠上占一个重要位置的数。


    素数有多少:高斯猜测,n以内的素数个数大约与n/lnn相当,或者说,当n很大时,两者数量级相同。这就是著名的素数定理。

    目前发现的最大的素数:18世纪发现的最大素数是2^31-1,19世纪发现的最大素数是2^127-1,20世纪末人类已知的最大素数是2^859433-1,用十进制表示,这是一个258715位的数字。


与素数有关的著名猜想有:
  1. 歌德巴赫猜想:大于2的所有偶数均是两个素数的和,大于5的所有奇数均是三个素数之和。其中第二个猜想是第一个的自然推论,因此歌德巴赫猜想又被称为1+1问题。我国数学家陈景润证明了1+2,即所有大于2的偶数都是一个素数和只有两个素数因数的合数的和。国际上称为陈氏定理。 
  2. 孪生素数猜想:差为2的素数有无穷多对。目前知道的最大的孪生素数是1159142985×22304-1和1159142985×22304+1。 
  3. 在n2与(n+1)2之间总有素数;n2+1这种形式的素数有无穷多个。 
  4. 大于某个n的自然数不是完全平方数,就是一个平方数与一个素数之和。 
素数求取问题:求出小于N的所有素数。
  1. 暴力求解:遍历[2,N]中的每一个数,判断其是否是素数。时间复杂度O(N^1.5)。
    public void printPrimes(int N){
        System.out.println(2);
        for(int i=3;i<N;i++){
            if(isPrime(i))
                System.out.println(i);
        }
    }
    
    boolean isPrime(int n){
        int sqrt = (int)Math.pow(n,0.5) +1;
        for(int i=2; i<sqrt; i++){
             if(n%i ==0)
                 return false;
        }
        return true;
    }


  2. 一次筛选:使用长为N+1的数组(位图更好),第i位表示i是否为素数。从第一个素数开始,将其输出,然后把后面所有它的倍数标记,找到下一个素数继续循环,直到最后。时间复杂度O(N),空间复杂度O(N)。
    public void printPrimes(int N){
        byte[] primes = new byte[N+1];
        for(int i=2; i<=N; i++)
            primes[i] = 1;
        int sqrt = (int)Math.sqrt(N) +1;
        for(int i=2; i<=N;i++){
            if(primes[i] == 0) continue;
            else System.out.println(i);
            if(i>sqrt) continue; //大于n平方根的就不用向后标记了,为什么呢?假设合数X<N,X的最小质因数x<sqrt(N),X一定会被x标记为合数
            for(int j=i<<1; j<=N; j+=i){
                primes[j] = 0;
            }
        }
    }


  3. 二次筛选:针对求L到U之间的所有素数问题。使用一次筛选方法空间开销有些大,因此可以先求出sqrt(U)以内的素数,然后用这些素数过滤掉L到U之间的合数即可。时间复杂度O(U^0.5+U-L),空间复杂度O(U^0.5+U-L)。
              public static void printPrimes(int L, int U){
    		int sqrtU = (int)Math.sqrt(U)+1;
    		byte[] lPrimes = new byte[sqrtU+1];
    		for(int i=2; i<=sqrtU; i++)
    			lPrimes[i] = 1;
    		//1次筛选
    		int sqrt = (int)Math.sqrt(sqrtU)+1;
    		for(int i=2;i<=sqrt; i++){
    			if(lPrimes[i]==0) continue;
    			for(int j=i<<1; j<=sqrtU; j+=i){
    				lPrimes[j] = 0;
    			}
    		}
    		//2次筛选
    		byte[] primes = new byte[U-L+1];
    		for(int i=0; i<primes.length; i++)
    			primes[i] = 1;
    		
    		for(int i=2; i<=sqrtU; i++){
    			if(lPrimes[i] == 0) continue;
    			//素数
    			int base = L/i+1;	
    			if(L%i ==0) base--;
    			base = base * i;	//大于等于L的p的最小倍数
    			while(base<=U){
    				primes[base-L] = 0;
    				base += i;
    			}
    		}
    		for(int i=0; i<primes.length; i++)
    			if(primes[i]==1)
    				System.out.println(i+L);
    	}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值