一、欧拉函数简单应用
·定义:
对于一个正整数n,它的欧拉函数的值即{p|p∈[1,n),p∈N+,p与n互质}的集合的大小,我们用φ(n)表示正整数n的欧拉函数
φ(n)=n(1-1/p1)(1-1/p2)……(1-1/pk),其中p1~pk为n的质因数
附证明:https://blog.csdn.net/paxhujing/article/details/51353672
·性质:
1)如果n是素数,那么φ(n)=n-1,逆向也成立
2)如果n是素数,k是正整数,那么φ(n^k)=(n-1)*n^(k-1)
证明:显然一共有n^k-1个正整数,其中能被n^k整除的有n*t,t∈{1,2……n^(k-1)-1},所以有[(n^k)-1]-[n^(k-1)-1]个
3)如果m,n是互质的正整数,那么φ(mn)=φ(m)φ(n)
证明:m,n没有公共约数,我们令p1~pk1表示m的质因数,q1~qk2表示n的质因数,我们由计算公式可得:
φ(m)φ(n)=m(1-1/p1)(1-1/p2)……(1-1/pk1)n(1-1/q1)(1-1/q2)……(1-1/qk2)
φ(mn)=mn(1-1/p1)(1-1/p2)……(1-1/pk1)(1-1/q1)(1-1/q2)……(1-1/qk2)
4)n=p1^a1*p2^a2*……*pk^ak为n的素数幂分解(根据唯一分解定理),那么φ(n)=n(1-1/p1)(1-1/p2)……(1-1/pk)
证明:你们一定行!
由性质3:
φ(n)=φ(p1^a1)φ(p2^a2)……φ(pk^ak)
=(p1-1)*p1^(a1-1)……(pk-1)*pk^(ak-1)
=p1^a1*……*pk^ak*(1-1/p1)*……*(1-1/pk)
5)一个数n的质因数的和=φ(n)*n/2
·练习:
#oj3623 Relatives
题目大意:求φ(n)
模板题,不难想到利用性质4来求φ(n),显然我们需要进行质因数分解,代码:
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n;
int euler1(int m){//直接求
int ans=m;
for(int i=2;i<=m;i++){
if(m%i==0){
// ans=ans*(1-1/i)=>
// ans=ans-ans/i=>
ans=ans/i*(i-1);//防止溢出
while(m%i==0)m/=i;
}
}return ans;
}
int euler2(int m){//O(√n)
int ans=m;
for(int i=2;i*i<=m;i++){//任意一个合数都有不大于根号n的约数
if(m%i==0){
ans=ans/i*(i-1);
while(m%i==0)m/=i;
}
}if(m>1)ans=ans/m*(m-1);//最后的pk
return ans;
}
#define MAXN 100001
int euler[MAXN];
int euler3(int m){//筛法求euler函数O(n),假的,千万级就跑得很慢了
for(int i=1;i<=m;i++)euler[i]=i;
for(int i=2;i<=m;i++)if(euler[i]==i){//利用性质1
for(int j=i;j<=m;j+=i)euler[j]=euler[j]/i*(i-1);
}return euler[m];
}
main(){
while(~scanf("%lld",&n)&&n)cout<<euler1(n)<<""<<euler2(n)<<""<<euler3(n)<<"\n";
#oj3624 原根
题目大意:给定奇素数,求它的原根
原根是个数学符号,它的定理:n的原根为φ(φ(n)),当结论背下来吧,感兴趣的同学可以去网上找这方面的资料
#oj2904 MMT数
题目大意:给定一个数n,需要我们求n与x不互质且x不为n的约数的个数(x<=n)
发现正面求解不太好搞,我们考虑逆向求解
对于第一个条件(求互质):ans1=n-φ(n)
对于第二个条件(求约数个数):我们由素数幂分解得到ans2=(a1+1)(a2+1)……(ak+1)个(详见性质4)
于是我们就得到了最终答案:ans=n-ans1-ans2个?
注意1又是n的约数且含在了φ(n)中,所以算了两次,因此我们要+1</