求对于1~n中每个数x在[1,x]区间内和x互质的数的个数
可以直接暴力枚举,辗转相除gcd(x,y)=1时互质
辗转相除法复杂度O(logN),所以该方法复杂度O(N^2·logN):
//最大公约数
#include
#include
using namespace std;
int n,tot;
int gcd(int x,int y){
if (y==0) return x;
else return gcd(y,x%y);
}
int main(){
freopen("phi.in","r",stdin);
freopen("phi1.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++){
int tot=0;
for (int j=1;j<=i;j++) if (gcd(i,j)==1) tot++;
printf("%d\n",tot);
}
return 0;
}
对于欧拉函数,phi(x)等于[1,x]区间内和x互质数的个数
设p1,p2,p3,……,pk是x所有互异质因子,则phi(x)=x·(1-1/p1)·(1-1/p2)·(1-1/p3)·……·(1-1/pk)
而且phi(x)是个积性函数,当a、b互质时phi(a·b)=phi(a)·phi(b)
主要还有两个特点:
1、若 x%y=0 则phi(xy)=phi(x)*y
2、若 x%y≠0 则phi(xy)=phi(x)*(y-1)
所以可以在线性筛(即欧拉筛法)的过程中直接求phi,复杂度为O(N):
//欧拉函数
#include
#include
using namespace std;
int phi[100005],prime[100005];
bool vis[100005];
int n,cnt;
int main(){
freopen("phi.in","r",stdin);
freopen("phi.out","w",stdout);
memset(vis,0,sizeof(vis));
scanf("%d",&n);
phi[1]=1;
cnt=0;
for (int i=2;i<=n;i++){
if (!vis[i])prime[++cnt]=i,phi[i]=i-1;
for (int j=1;j<=cnt&&i*prime[j]<=n;j++){
vis[prime[j]*i]=1;
if (i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
for (int i=1;i<=n;i++) printf("%d\n",phi[i]);
return 0;
}
2016/12/22 20:35:41
Ending.