线性筛和牠的伙伴们 : OI数论(1)

1.线性筛

我们知道一种筛法,叫艾氏筛,复杂度为O(NloglogN)

这个算法的复杂度的确很小,但是并不是严格线性的,接下来隆重介绍真正的线性筛法——欧拉筛

首先,我们先要知道为什么艾氏筛不能做到线性呢?是因为它的很多数都被重复筛了好多遍

那么怎么避免重复筛呢?我们考虑每个数最小的质因子来筛它

我们需要两个数组,prime和v,prime代表了当前已经筛出的素数,v[x]代表x的最小质因数

考虑以下步骤来得出答案:
1.若当前v[i]=0,说明 i 是素数,加入prime末尾,此时显然v[i]=i
2.扫描不大于v[i]的所有质数p,令v[ip]=p

主体代码如下

const int N = 11414514 ;//臭名远扬
int v[N];
vector<int> prime;
void pri(int n)
{
    memset(v,0,sizeof(v));
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0) v[i]=i,prime.push_back(i);
        for(int j=0;j<prime.size();j++)
        {
            if(prime[j]>v[i] || prime[j]>n/i) break;
            v[i*prime[j]]=prime[j];
        }
    }
}

具体证明的话是利用算术基本定理,事实上搞懂v的含义就能理解后面的扩展运用了

2.互质和欧拉函数

互质的定义:a,bN,gcd(a,b)=1,a,b

欧拉函数的定义:ϕ(N)1NN

欧拉函数的计算式:ϕ(N)=Np|N(11p)

上式证明?设pN的质因子,1-N中p的倍数有N/p个,q也是N的质因子,则q的倍数有N/q,按照容斥原理,1-N中不含有pq质因子的数为

NNpNq+Npq=N(11p)(11q)

推广一下,就可以得出上式了

3.线性筛+欧拉函数性质线性算欧拉函数之和

现在我们需要算i1nϕ(i)如果我们一个一个算的话需要质因数分解,十分浪费时间,接下来介绍线性计算方式

先明确两个性质

性质1:若p|iϕ(ip)=pϕ(i)
性质2:若piϕ(ip)=(p1)ϕ(i)

如果你一定要问证明,那么可以参考各种算法书上的,笔者没有精力写了

知道了这两个性质,再利用线性筛,就可以线性地求欧拉函数的和了

const int N = 114514;//再次臭名昭著
int v[N],phi[N];//phi[i]代表了欧拉函数(i)的值
vector<int> prime;
void euler(int n)
{
    memset(v,0,sizeof(v));
    for(int i=2;i<=n;i++)
    {
        if(v[i]==0)
        {
            v[i]=i;
            prime.push_back(i);
            phi[i]=i-1;
        }
        for(int j=0;j<prime.size();j++)
        {
            if(prime[j]>v[i] || prime[j]>n/i) break;
            v[i*prime[j]]=phi[i]*(i%prime[j]?(prime[j]-1):prime[j]);//根据两条性质写出来的式子
        }
    }
}
posted @   羊扬羊  阅读(83)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示