欧拉筛(线性筛)& 欧拉函数

今天又复习了一下欧拉筛法,在这做个笔记。

欧拉筛(线性筛)

一般情况下,有一种筛法叫埃什么什么的。是 O(nloglogn) ,非常接近于 O(n) ,但也会有坑爹的出题人来个10000000故意卡你。

原理

这可能原理有点妙啊。

  • pr[i] 为i最小质因子,然后从2开始计算
  • 如果 pr[i] 没有在前面得到,就说明i是质数,所以 pr[i]=i,prime[++len]=i
  • 对于i,枚举每一个不超过 pr[i] 的质数 prime[j] ,所以 pr[iprime[j]]=prime[j]

这样可以发现,每一个数只会被它最小的质因子筛去,所以保证了算法为 O(n) 的。

我们见一下代码:

代码

void find_prime(int n)
{
    memset(isprime,0,sizeof(isprime));
    sp = 0;
    for(int i = 2;i <= n;i++)
    {
        if(!isprime[i])
        {
            prime[++sp] = i;
            isprime[i] = i;
        }
        for(int j = 1;j <= sp && i * prime[j] <= n;j++) {
            isprime[i*prime[j]] = prime[j];
            if(prime[j] >= isprime[i]) break;//用isprime[i]来表示i的最小质因子,可能用mod比较慢 
        }
    }
}

在break那一行,有的人会用
      if(i % prime[j]==0) break;
不过也可以通过isprime[i]保存i最小的质因子来与prime[j]做比较。
但不管怎么写,我人认为最重要的就是含break的那个语句

欧拉函数

不过,仅仅筛素数就显得线性筛不是那么必要。
线性筛最科学的战场——求积性函数
作为蒟蒻,我以欧拉函数来举例:

代码

先粗浅地看一下代码

void find_prime(int n)
{
    memset(isprime,0,sizeof(isprime));
    sp = 0;
    for(int i = 2;i <= n;i++)
    {
        if(!isprime[i])
        {
            prime[++sp] = i;
            isprime[i] = i;
            phi[i] = i-1;//①
        }
        for(int j = 1;j <= sp && i * prime[j] <= n;j++) {
            isprime[i*prime[j]] = prime[j];
            if(prime[j] >= isprime[i]) {
                phi[i*prime[j]] = phi[i]*prime[j];//②
                break;
            }
            phi[i*prime[j]] = phi[i]*(prime[j]-1);//③
        }
    }
}

原理

  1. 每个数字只会被筛到一次
  2. 当正整数p为素数时, phi[p]=p1
  3. 欧拉函数既然是积性函数,就说明当a与b互质时,满足 phi(ab)=phi(a)phi(b)
  4. 当p为素数时, phi(pk)=(p1)pk1
  5. 我们保证了每次的 prime[j] 小于等于i的最小质因子,所以当 prime[j]<isprime[i] 时, phi[iprime[i]]=phi[i]phi[j]=phi[i](j1) ,而在i%prime[j]==0时,直接乘上 prim[j]

上述的五点:1表明每个数值被算一次。2解释了①。3、4、5解释了②和③。

还有,本文参考:http://www.cnblogs.com/zhuohan123/p/3233011.html

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值