/*根据三条性质推导即可。
线性筛中每一个数字最多只会被筛一次,因此正好可以对每一个数字求欧拉函数。
线性筛正好是由小的数字筛到大的数字 or 正好是指数
前者用后两条性质 后者用第一条性质即可。
三条性质如下:
1.如果n为某一素数的幂次,那么: φ(p^a)=(p-1)*p^(a-1) (φ(p)=p-1)
2.如果i mod p=0,那么φ(i*p)=p*φ(i)
3.如果i mod p≠0,那么φ(i*p)=φ(i)*(p-1)*/
#include <bits/stdc++.h>
using namespace std;
#define MAXN 10000000
bool f[MAXN+10];
int phi[MAXN+10],pri[MAXN+10],cnt;
void Get_phi(int n)//欧拉筛
{
int i,j;
phi[1]=1;
for(i=2;i<=n;i++){//循环赋值
if(!(f[i])){//判断是否为素数
pri[++cnt]=i;//保存新筛素数
phi[i]=i-1;//欧拉筛性质1
}
for(j=1;j<=cnt&&i*pri[j]<=n;j++){
f[i*pri[j]]=1;
if(i%pri[j]==0) {//判断是否为i是否为已知素数的倍数
phi[i*pri[j]]=phi[i]*pri[j];//欧拉筛性质2
break;
}
else phi[i*pri[j]]=phi[i]*(pri[j]-1);//欧拉筛性质3
}
}
}
int main()
{
int n;
scanf("%d",&n);
Get_phi(n);
printf("cnt:%d\n",cnt);
for(;n;n--)
{
printf("%d %d\n",n,phi[n]);
}
return 0;
}
欧拉筛知识代码实现,今日份学习



京公网安备 11010502036488号