欧拉线性筛素数

欧拉线性筛素数

原理:

简单说明一下,其筛选的原理就是,当一个数是素数时,这个数的2,3,4,,,,n倍肯定都不是素数。

代码:

bool isnotprime[INF]={1,1};   //isnotprime[i] 判断i是否为素数  0代表是素数 1代表不是素数
int prime[INF]={0};          //prime[i]为第i个素数,从0开始
int num=0;                  //num为素数个数;
void setprime(int n)         //求小于n的素数;   
{                                   
    num=0;
    for(int i=2;i<n;i++)
    {
        if(!isnotprime[i])
        {                                         
            prime[num++]=i;                       
        }                                        
        for(int j=0;j<=num&&i*prime[j]<n;j++)                   
        {                                         

            isnotprime[i*prime[j]]=1;
            if(!(i%prime[j]))   
            break;
        }                             
    }
} 

详解:

bool isnotprime[INF]={1,1};  ///即isnotprime[0]=1;isnotprime[1]=1;

因为0和1都不是素数,所以置为1。

    for(int i=2;i<n;i++)
    {
        if(!isnotprime[i])  
        {                                        
            prime[num++]=i;                      
        }

第一层for循环,判断 i 是否是素数。i=2时,isnotprime[ 2 ]=0,即是素数。将其放入素数数组prime里面。素数个数加1。

        for(int j=0;j<=num&&i*prime[j]<n;j++)                                                   {           
            isnotprime[i*prime[j]]=1;
            if(!(i%prime[j]))   
            break;
        }
     }

第二层for循环,将现有的所有素数的第 i 倍筛选掉。即 isnotprime[ i * prime [ j ] ]置为1。

i=2时,仅能将4筛掉,即isnotprime[ 2 * 2 ]=1;

if(!(i%prime[j]))
break;

原理是利用了每个合数必有一个最小素因子,每个合数仅被它的最小素因子筛去正好一次,当 i 能整除 prime[ j ],那么i * prime[ j+1 ] 这个合数肯定被 prime[j] 乘以某个数筛掉,因为 i 中有prime[j]且 i * prime[ j+1 ]中也有prime[ j ]。

举个例子:

当 i = 8,prime[ ] = 2,3,5,7;

i * prime[ ] = 16,24,40,56;

因为8 % 2 = 0,所以24,40,56,可以不筛,直接break;

就如上面那句话所说的,当8能整除2时,8乘以 下一个素数3 的值24,将会被12乘以2筛掉。

即24 = 8 * 3=(2 * 4) * 3 = 2 * (4 * 3) = 2 * 12; 被12筛掉

​ 40 = 8 * 5=(2 * 4) * 5 = 2 * (4 * 5) = 2 * 20; 被20筛掉

​ 56 = 8 * 7=(2 * 4) * 7 = 2 * (4 * 7) = 2 * 28; 被28筛掉

这些数后面会被筛掉,即 i = 12,20,28时。所以现在就不用筛选,降低时间复杂度。

代码执行过程:

i最新确定的素数( prime[] )最新确定的非素数( isnotprime[] )
224 (2 * 2)
336 (3 * 2)、9 (3 * 3)
48 (4 * 2)
5510 (5 * 2)、15 (5 * 3)、25 (5 * 5)
612 (6 * 2)
7714 (7 * 2)、”21”(7 * 3)、”35”(7 * 5)、”49”(7 * 7)
8“16”(8 * 2)
9“18”(9 * 2)、“27”(9 * 3)
10“20”(10 * 2)
1111“22”(11 * 2)、”33”(11 * 3)、”55”(11 * 5)、”77”(11 * 7)、”121”(11 * 11)
12“24”(12 * 2)
1313“26”(13 * 2)、”39”(13 * 3)、”65”(13 * 5)、”91”(13 * 7)、”143”(13 * 11)、“169”(13 * 13)
14“28”(14 * 2)
15“30”(15 * 2)、“45”(15 * 3)

此表为求15以内的素数代码执行过程。

打引号的为大于15的非素数,可以不筛。

加粗的为break的地方。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值