\(\varphi(x)\)表示\(x\)以内与\(x\)互质的个数
\(\varphi(x)=x*\prod\limits_{i=1}^n(1-\dfrac{1}{p_i})\) \(p_i\)为x的质因数
特殊的 \(\varphi(1)=1\)
其中\(p_1,p_2……p_n\)Ϊ\(x\)的所有质因数(\(x\)是正整数)
那么,怎么理解这个公式呢?
对于\(x\)的一个质因数\(p_i\),因为\(x\)以内\(p_i\)的倍数是均匀分布的,所以\(x\)以内有\(\frac {1}{p_i}\)的数是\(p_i\)的倍数
对应的,有\(1-\dfrac {1}{p_i}\)的数不是\(p_i\)
同理,对于\(p_j\)有\(1-\frac {1}{p_j}\)的数不是\(p_j\)的倍数
所以有\((1-\frac {1}{p_i})*(1-\frac {1}{p_j})\)的数既不是\(p_i\)的倍数,又不是\(p_j\)的倍数
当有函数\(f(x)\),\(m\)与\(n\)互质时,\(f(m)*f(n)=f(m*n)\)称为积性函数
对任意整数\(m\)与\(n\),\(f(m)*f(n)=f(m*n)\)称为完全积性函数
对于质数\(p\),\(\varphi(p)=p-1\)
证明:这貌似不需要证明吧qwq对于质数p,\(\varphi(p^k)=p^k-p^{k-1}\)
证明:\(\varphi(p^k)=p^k*(1-\dfrac{1}{p})\)欧拉函数是积性但飞完全积性函数,对于\(m\)与\(n\)互质时,有\(\varphi(m)*\varphi(n)=\varphi(m*n)\)
特殊的,\(m=2\)且\(n\)为奇数,\(\varphi(m)*\varphi(n)=\varphi(n)\)
证明:\(m\)与\(n\)互质,说明没有公共质因数,\(m*n\)质因数为\(m\)的质因数+\(n\)的质因数当\(n>2\)时,\(\varphi(n)\)为偶数
证明:有基本事实\(gcd(a,b)=1\) \(gcd(a,a-b)=1\),说明质因数都是成对出现的对于小于\(n\)且与\(n\)互质的数,总和=\(\varphi(n)*n/2\)
证明:对于与\(n\)互质的数\(m\),有对立的\(n-m\)与\(n\)互质,\(m\)与\(n-m\)的平均数又为\(n/2\),\(\varphi(n)\)又为偶数\(n=\sum\limits_{d|n}\varphi(d)\)
设函数\(F(n)=\sum\limits_{d|n}\varphi(d)\)
若\(m\)与\(n\)互质
\(F(m)*F(n)=\sum\limits_{i|m}\varphi(i)*\sum\limits_{j|n}\varphi(j)\)
\(=\varphi(i_1)*\varphi(j_1)+\varphi(i_1)*\varphi(j_2).....+\varphi(i_{km})*\varphi(j_{kn})\)
\(=\varphi(i_1*j_1)+\varphi(i_1*j_2).....+\varphi(i_{km}*j_{kn})\) m与n互质,故因数也必全互质
\(=\sum\limits_{k|m*n}\varphi(k)\) 可以发现,\(i_1*j_1,i_1*j_2.....i_{km}*j_{kn}\)这些数为\(n*m\)的因数
\(=F(m*n)\)
设合数\(n=p1^{k1}*p2^{k2}.....*pm^{km}\)则\(F(n)=F(p1^{k1}*F(p2^{k2}).....*F(pm^{km}))\)
利用性质2易证\(F(pm^{km})=pm^{km}\),则\(F(n)=p1^{k1}*p2^{k2}.....*pm^{km}=n\)
单个:\(2\)~\(\sqrt{(n)}\)扫一遍就好了,素数怎么求这个就怎么求
要是求<=n所有数的欧拉函数呢?
埃拉托斯特尼筛求欧拉函数 \(O(n(log(n))(loglogn))\)
就是普通的找质数,把倍数都筛一遍(质因数的贡献)
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)//把i的倍数筛一遍 phi[j]=phi[j]/i*(i-1); }
欧拉筛求欧拉函数 \(O(n)\)
先来了解一下欧拉筛
for(int i=2;i<=n;i++){ if(!vis[i])//不是目前找到的素数的倍数 prime[cnt++]=i;//找到素数~ for(int j=0;j<cnt&&i*prime[j]<=n;j++){ vis[i*prime[j]]=true;//找到的素数的倍数不访问 if(i%prime[j]==0) break;//关键!!!! } }
很多人对 $ if(i%prime[j]==0) break; $ 这一句都不太理解
找到一种很好的解释:
当\(i\)是\(prime[j]\)的倍数时,\(i=k*prime[j]\),如果继续运算 \(j+1\),\(i*prime[j+1]=prime[j]*k*prime[j+1]\)
这里\(prime[j]\)是最小的素因子,当\(i=k*prime[j+1]\)时会重复
这里是利用最小素因子优化,使得欧拉筛达到了优秀的线性\(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]];//利用了欧拉函数是个积性函数的性质 } } }