目录
前言
欧拉筛就不多做介绍,我们可以用欧拉筛的思想去筛一些积性函数的值
欧拉函数(phi
):
bool sta[1000005];
int pri[500000];
int phi[500000];
int cnt;
void oula(int n){
sta[1]=1,phi[1]=1;
for(int i=2;i<=1000005;i++){
if(!sta[i])pri[++cnt]=i,phi[i]=i-1//质数的phi值为其本身减1
for(int j=1;j<=cnt&&pri[j]*i<=1000005;j++){
sta[pri[j]*i]=1;//再也没翻身做质数的机会了
if(i%pri[j]==0){//i是pri[j]的倍数
phi[pri[j]*i]=phi[i]*pri[j];
break;
}
phi[pri[j]*i]=phi[i]*(pri[j]-1);
}
}
}
约数个数(tau
):
bool sta[1000005];
int pri[500000];
int tau[1000005];
int g[1000005];//对于任意正整数,我们可以对其进行质因数分解,g就是分解后各项中的最小次幂+1;
int cnt;
void oula(int n){
sta[1]=1,phi[1]=1;
for(int i=2;i<=1000005;i++){
if(!sta[i])pri[++cnt]=i,tau[i]=2,g[i]=2;
for(int j=1;j<=cnt&&pri[j]*i<=1000005;j++){
sta[pri[j]*i]=1;//再也没翻身做质数的机会了
if(i%pri[j]==0){//i是pri[j]的倍数
tau[pri[j]*i]=tau[i]*(g[i]+1)/g[i];
g[pri[j]*i]= g[i]+1;
break;
}
tau[pri[j]*i]=tau[i]*2,g[pri[j]*i]=2;
}
}
}
莫比乌斯函数(mu
):
有时我们会遇到求前缀和,只需加上一段代码就行:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool sta[500500];
ll pri[500500];
ll mu[500500];
ll sum[500500];
ll cnt;
void oula(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!sta[i])pri[++cnt]=i,mu[i]=-1;
for(int j=1;j<=cnt&&pri[j]*i<=n;j++){
sta[pri[j]*i]=1;
if(i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
}
for(int i=1;i<=1000005;i++){
sum[i]=sum[i-1]+phi[i];
}
Summary:
欧拉筛广泛运用于积性函数求值,灵活运用,事半功倍