在数论,对正整数n,欧拉函数是小于或等于n的正整数中与n互质的数的数目
φ(x)=x ∏ i = 1 N ( 1 − 1 p i ) \prod_{i=1}^N{(1-\frac{1}{p_i})} ∏i=1N(1−pi1) (其中p1, p2……pn为x的所有质因数)
我觉得网上许多博客的证明不太严谨,我严格证明一下
首先明白两个性质
1:当n= p k p^k pk (且p是质数的情况下) φ(n)= p k p^k pk- p k − 1 p^{k-1} pk−1
因为显然n的质因子只有一个就是p,那么1-n中不和他互素的就是因子含有p的数即 p×1,p×2,p×3… p× p k − 1 p^{k-1} pk−1即总共有 p k − 1 p^{k-1} pk−1个数,而总数有 p k p^{k} pk,那么结果就是 p k p^{k} pk- p k − 1 p^{k-1} pk−1
2:欧拉函数是积性函数,但不是完全积性函数。若m,n互质,则φ(m∗n)=φ(m)∗φ(n),这个我不会证明,直接看维基百科的证明吧:证明:设A, B, C是跟m, n, mn互质的数的集,据中国剩余定理,A×B×C可建立双射(一一对应)的关系
而x= p 1 k 1 {p_1}^{k_1} p1k1 × p 2 k 2 {p_2}^{k_2} p2k2 × p 3 k 3 {p_3}^{k_3} p3k3… p n k n {p_n}^{k_n} pnkn
φ(x)=( p 1 k 1 {p_1}^{k_1} p1k1- p 1 k 1 − 1 {p_1}^{{k_1}-1} p1k1−1)( p 2 k 2 {p_2}^{k_2} p2k2- p 2 k 2 − 1 {p_2}^{{k_2}-1} p2k2−1)…( p n k n {p_n}^{k_n} pnkn- p n k n − 1 {p_n}^{{k_n}-1} pnkn−1)=x ∏ i = 1 N ( 1 − 1 p i ) \prod_{i=1}^N{(1-\frac{1}{p_i})} ∏i=1N(1−pi1)
1:对于质数p,φ ( p )=p−1。显然
2:…
还有一些其他性质,暂时不要用到,先不再学习
复杂度是n× n 2 \sqrt[2]{n} 2n
#include
#include
#include
#include
#include
#include
#include
#define fi first
#define se second
#define debug printf("I am here\n");
using namespace std;
typedef long long ll;
const int maxn=3e5+5,inf=0x3f3f3f3f,mod=998244353,lim=1e7+5e6;
const ll INF=0x3f3f3f3f3f3f3f3f;
int t,n;
int euler(int x){
int ans=x;
for(ll i=2;i*i<=x;i++){
if(x%i==0){
ans=ans/i*(i-1);
while(x%i==0){
x=x/i;
}
}
}
if(x!=1){
ans=ans/x*(x-1);
}
return ans;
}
int main(){
scanf("%d",&t);
while(t--){
scanf("%d",&n);
printf("%d\n",euler(n));
}
return 0;
}
但是如果n比较大,要求[1,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的倍数更新掉
}
}
}
}
既然有埃式,那么就有线性筛,线性筛有点难懂
前提是要懂欧拉筛。每个数被最小的因子筛掉的同时,再进行判断。i表示当前做到的这个数,prime[j]表示当前做到的质数,那要被筛掉的合数就是i*prime[j]。若prime[j]在这个合数里只出现一次(i%prime[j]!=0),也就是i和prime[j]互质时,则根据欧拉函数的积性函数的性质,phi[i * prime[j]]=phi[i] * phi[prime[j]]。若prime[j]在这个合数里出现了不止一次(i%prime[j]=0),也就是这个合数的所有质因子都在i里出现过,那么根据公式,φ(i * prime[j])=prime[j] * i * ∏ i = 1 N ( 1 − 1 p i ) \prod_{i=1}^N{(1-\frac{1}{p_i})} ∏i=1N(1−pi1) 。复杂度为O(n)。
还是看代码吧:
void euler(int n){
phi[1]=1;//1要特判
for (int i=2;i<=n;i++){
if (flag[i]==0){//这代表i是质数
prime[++num]=i;
phi[i]=i-1;
}
for (int j=1;j<=num&&prime[j]*i<=n;j++)//经典的欧拉筛写法
{
flag[i*prime[j]]=1;//先把这个合数标记掉
if (i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];//若prime[j]是i的质因子,则根据计算公式,i已经包括i*prime[j]的所有质因子
break;//经典欧拉筛的核心语句,这样能保证每个数只会被自己最小的因子筛掉一次
}else{
phi[i*prime[j]]=phi[i]*phi[prime[j]];//利用了欧拉函数是个积性函数的性质
}
}
}
}
参考链接:https://blog.csdn.net/liuzibujian/article/details/81086324