线性筛素数及欧拉函数打表。

传统的筛法筛素数由于会重复标记所以会出现多余的操作,导致复杂度上升。这里有一个线性筛素数的方法可以在O(n)的复杂度内将所有非素数标记出来。

 

首先 ,一个非素数可以看作是多个素数的乘积,如10 可以看作2和5,14 看作2,7, 25==5*5 ,36=2*3*3*2 

那么一个数一定由一个最小的质因子,乘以某个数的来的。并且这个关系一定是一一对应的。 可以自己画表尝试验证一下。

那么我们从2开始筛,小于=2的质数有2  ,所以 得到2*2 = 4 标记为非质数。  然后是3  小于等于3的有 2 ,3 所以得到 6 与 9 为非素数。 然后是4*2 = 8  , 5*2=10 5*3=15 5 * 5 = 25;一直推到下去,即,每个数乘比他小的素数即可。并且那个素数如果是乘积数的质因子。则跳出本次筛素数。因为,我们要做到一一对应。如果继续筛下去,会重复。 就如上面举得例子,4*3 =12  6*2 = 12 这样就被筛了两次。所以不行。

#include<stdio.h> 
const int maxs = 1e6+1;
bool vis[maxs+10];
int prime[maxs+10];
int phi[maxs+10];
void Elu()
{
    phi[1]=1;  
    int top = 0;   
    for(int i = 2; i<=maxs;i++)
    {
        if(vis[i]==0)//vis[i]== 0 说明该数为质数,则phi[i]=i-1;
        {
            prime[top++] = i; 
            phi[i] = i-1;   
        }
        for(int j = 0 ;j<top && i*prime[j]<maxs;j++) // i*prime[j] <maxs 防止越界 
        {
            vis[prime[j]*i] = 1;    //筛出一个非素数
            if(i%prime[j]==0)
            {
                phi[i*prime[j]] = phi[i] * prime[j]; //此时prime[j]为i的一个质因子。由公式得到phi[i]的值 
                break;
            }
            else
            {
                phi[i*prime[j]] = phi[i] * phi[prime[j]] ;//此时i与prime[j]互质 由公式得到phi[i];
            }
        }
    }
    return ;
}
int get_phi(int n)
{
    int ans = n;
    for(int i = 2; i*i <= n;i++)
    {
        if(n%i==0)
        {
            ans = (ans/i) * (i-1);  //化简可得 ans = ans(1-1/p);
            while(n%i==0)
            {
                n=n/i;   //将相同的质因子去掉。
            }
        }
    }
    if(n!=1)
    {
        ans = (ans/n) * (n-1); //如果剩下的n非1,说明仍残留一个数,此时n如上面的i一样看待。
    }
    return ans;
}
int main()
{
    Elu();
    for(int i = 1;i<=20;i++)
    {
        printf("%d   phi[%d]=%d   get_pgi(%d) == %d\n",prime[i],i,phi[i],i,get_phi(i));
    }


}

以上为代码段,一般用线性筛法是用来打欧拉函数表的。所以我就放一块了。

接下来说说欧拉函数是什么梗。

欧拉函数就是给你一个n  返回 [1 n]中  与n最大公因数为1的数的个数。

普通求解方法由唯一定理求解。即n个质因子相乘会得到一个合数。

设第i个质因子 为 Pi 则 [1,N]中 Pi的倍数为 N/Pi  。 由容斥定理得到。 满足欧拉函数定义的数的个数为

 emmm.我也不知道这个公式这个怎么用,只会写成这样了。 个数  = N -(N/P1+N/P2+N/P3+N/P4.....-N/P1P2 - N/P1P3 - N/P2P3 .......+N/P1P2P3P4P5....Pn);

反正推导出来结果就是     个数   =  n(1-1/P1)*(1-1/P2)*(1-1/P3)......;

直接求欧拉函数的复杂度为O(质因子个数)。  

这里我们就设欧拉函数为phi(n)吧。

如果是由线性筛法的话,我们又要想到   一个质数的欧拉函数的值一定为质数的值减1.   比如phi(13)=12;

并且,m1,m2,两个数如果互质的话,phi(m1*m2)==  phi(m1)*phi(m2);

并且 由phi (n) = n(1-1/P1)*(1-1/P2)*(1-1/P3)......;可知,当n乘以一个本身的质因子的时候,质因子个数是不会变得。

那么   phi(n*Pi)=n*Pi*(1-1/P1)*(1-1/P2)*(1-1/P3)

所以可以由这些性质筛出范围内的素数。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值