欧拉函数求个数
时间复杂度 O(sqrt(n))
ll eular(ll n){ ll ret=1,i; for (i=2;i*i<=n;i++) if (n%i==0){ n/=i,ret*=i-1; while (n%i==0) n/=i,ret*=i; } if (n>1) ret*=n-1; return ret; }
筛欧拉函数 + 素数
时间复杂度 O(n)
//欧拉线性筛:在线性时间内筛素数的同时求出所有数的欧拉函数 int tot; int phi[MAXN];//保存各个数字的欧拉函数 int prime[MAXN]; //按顺序保存素数 bool mark[MAXN];//判断是否是素数 void get_phi(){ phi[1] = 1; for(int i = 2; i <= MAXN; i++){//相当于分解质因数的逆过程 if(!mark[i]){ prime[++tot] = i; phi[i] = i-1; } for(int j = 1; j <= tot; j++){ if(i * prime[j] > N) break; mark[i * prime[j]] = 1;//确定i*prime[j]不是素数 if(i % prime[j] == 0){//判断prime[j] 是否为 i的约数 phi[i * prime[j]] = phi[i] * prime[j]; break; } else{//prime[j] - 1 就是 phi[prime[j]],利用了欧拉函数的积性 phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } }
欧拉函数的几个性质
1.对于质数p,φ(p)=p−1 φ(p)=p-1φ(p)=p−1。
2.若p为质数,n=pk n=p^kn=p
k
,则φ(n) φ(n)φ(n)=pk p^kp
k
-pk−1 p^{k-1}p
k−1
。
3.欧拉函数是积性函数,但不是完全积性函数。若m,n互质,则φ(m∗n)=φ(m)∗φ(n) φ(m*n)=φ(m)*φ(n)φ(m∗n)=φ(m)∗φ(n)。特殊的,当m=2,n为奇数时,φ(2*n)=φ(n)。
4.当n>2时,φ(n)是偶数。
5.小于n的数中,与n互质的数的总和为:φ(n) * n / 2 (n>1)。
6.n=∑d∣nφ(d) n=sum_{d|n}{φ(d)}n=∑ d∣n φ(d),即n的因数(包括1和它自己)的欧拉函数之和等于n。
求欧拉函数另一个代码
埃拉托斯特尼筛求欧拉函数
这个复杂度虽然不是O(n),但还是挺快的(据说是O(n*ln ln n)
void euler(int n) { for (int i=1;i<=n;i++) phi[i]=i; for (int i=2;i<=n;i++) { if (phi[i]==i)//这代表i是质数 { for (int j=i;j<=n;j+=i) { phi[j]=phi[j]/i*(i-1);//把i的倍数更新掉 } } } }
上面来自原文:https://blog.csdn.net/liuzibujian/article/details/81086324