欧拉函数

匿名 (未验证) 提交于 2019-12-02 23:30:02

欧拉函数

定义

欧拉函数是小于x的整数中与x互质的数的个数,一般用 φ(x) 表示。特殊的,φ(1)=1

计算公式

xx 的所有素因子分别为 p1,p2,...pnp_1,p_2,...p_n,则
φ(x)=x×1n(11pi) φ(x)=x×\prod^{n}_{1}(1-\frac{1}{p_i})
用容斥原理证明即可

积性函数

欧拉函数是积性函数,当 gcd(n,m)=1 时,φ(n×m)=φ(n)×φ(m)

常用性质

  • 对于素数 ppφ(p)=p1φ(pk)=pkpk1φ(p)=p-1,φ(p^k)=p^k-p^{k-1}
  • n>2 时,φ(n) 是偶数,即当 gcd(m,n)=1 时,有 gcd(nm,m)=1,和 n 互素的数总是成对出现
  • 根据上一条可得,小于 n 的数中,与 n 互质的数的总和为 φ(n)×n/2(n>1)
  • n=dnφ(d)n=\sum_{d|n}φ(d) ,即 nn 的因数(包括1和本身)的欧拉函数之和等于 nn

实现代码

  • 根据公式计算 φ(n)φ(n) 直接枚举 nn 的所有素因子,复杂度和因式分解相同 O(n)O(\sqrt{n})
int phi(int n){ 	int m=sqrt(n)+0.5; 	int ans=n; 	for(int i=2;i<=m;++i){ 		if(n%i==0){ 			ans=ans/i*(i-1); 			while(n%i==0) n/=i; 		} 	} 	if(n>1) ans=ans/n*(n-1); 	return ans; } 
  • 埃氏筛,找到一个素数,更新它和它的倍数,复杂度 O(n×lnln(n))O(n×lnln(n))
int phi[maxn];  void init(){ 	for(int i=1;i<maxn;++i) phi[i]=i; 	for(int i=2;i<maxn;++i){ 		if(phi[i]==i){//代表i是素数 			for(int j=i;j<maxn;j+=i){ 				phi[j]=phi[j]/i*(i-1); 			} 		} 	} } 
  • 欧拉筛,每个数被最小的因子筛掉的同时,再进行判断。ii 表示当前做到的这个数,prime[j]prime[j] 表示当前做到的质数,那要被筛掉的合数就是 iprime[j]i*prime[j],若 i%prime[j]0i \ \% \ prime[j]\neq0,也就是 gcd(i,prime[j])=1gcd(i,prime[j])=1 互质时,则根据欧拉函数的积性函数的性质,φ(iprime[j])=φ(i)×φ(prime[j])φ(i * prime[j])=φ(i) ×φ(prime[j])。若 i%prime[j]=0i \ \% \ prime[j]=0,也就是这个合数的所有质因子都在i里出现过,那么根据公式,
    φ(i×prime[j])=i×prime[j]×k=1n(11pk)=prime[j]×φ(i) φ(i×prime[j])=i×prime[j]×\prod_{k=1}^{n}(1-\frac{1}{p_k})=prime[j]×φ(i)

    int prime[maxn],tot; int vis[maxn],phi[maxn];  void init(){ 	phi[1]=1; 	for(int i=2;i<maxn;++i){ 		if(!vis[i]){ 			prime[tot++]=i; 			phi[i]=i-1; 		} 		for(int j=0;j<tot && 1LL*i*prime[j]<maxn;++j){ 			vis[i*prime[j]]=1; 			if(i%prime[j]) phi[i*prime[j]]=phi[i]*phi[prime[j]]; 			else{ 				phi[i*prime[j]]=phi[i]*prime[j]; 				break; 			} 		} 	} } 
文章来源: https://blog.csdn.net/xiao_k666/article/details/89736285
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!