欧拉函数&最大公约数

来源:互联网 发布:hostease端口 编辑:程序博客网 时间:2024/05/29 18:30

  求对于1~n中每个数x在[1,x]区间内和x互质的数的个数

  可以直接暴力枚举,辗转相除gcd(x,y)=1时互质

  辗转相除法复杂度O(logN),所以该方法复杂度O(N^2·logN):

//最大公约数 #include<cstdio>#include<cstring>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<cstdio>#include<cstring>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.


0 0
原创粉丝点击