欧拉函数
1~N中与N互质的数的个数被称为欧拉函数,记为(φ(N));
例如:
(φ(1)=1); 区间1~1内,与1互质的数为1
(φ(2)=1), 区间1~2内,与2互质的数为1
(φ(3)=2), 区间1~3内,与3互质的数为1,2
(φ(4)=2); 区间1~4内,与4互质的数为1,3
通过上述几个简单的例子,我们能够发现定义中与N互质的数是指与N的最大公约数为1的数(其实说这句话只是想表达1与任何数互质)
于是我们有了第一个推论,若p是质数,则(φ(p)=p-1),记住(φ(1)=1)是一个特例!!!
证明:这个很好理解吧,若p是质数,则1~p内只有p本身与p不互质(或者说p的因子只有1和p本身,但1与p也算是互质的);
还有第二个推论,如果p是质数,则(φ(p^a)=(p-1)*p^{a-1});
证明:因为区间1~(p^a)内比(p^a)小的数有(p^a-1)个,那么有(p^{a-1}-1)个数被p整除;(举个例子,若p=2,a=3,则比(2^3)小的数有(2^3-1)个,有(2^2-1)个数被2整除,即2,4,8三个数)
所以有(φ(p)=p^a-1-(p^{a-1}-1)=(p-1)*p^{a-1})
再来第三个推论,若a和b互质,则(φ(a*b)=φ(a)*φ(b))
证明:区间1~ab中只有既与a互质又与b互质的数满足与ab互质的条件,而这样的数两两之间可以任意组合,则有(φ(a)*φ(b));
欧拉函数的线性筛法
先给出以下三条性质:(p为质数)
①:(φ(p)=p-1)
②:(φ(p*i)=p*φ(i)) (当(p)%(i==0)时)
③:(φ(p*i)=(p-1)*φ(i)) (当(p)%(i!=0)时)
其实欧拉函数的线性筛法与线性筛质数类似(或者说结合了线性筛质数更为恰当,因为看完代码就会发现线性筛欧拉函数就是在线性筛质数的板子上稍加修改)
void get_phi(){
phi[1]=1;
//phi[]即欧拉函数,phi[1]=1即φ(1)=1
for(int i=2;i<=N;i++){
if(!v[i]){
//v[i]表示i的最小质因子
v[i]=i;
prime[++tot]=i;
phi[i]=i-1;
//i是质数,则i的最小质因子就是它本身
//prime是记录质数的数组,tot统计质数个数
//因为i是质数,根据上述性质一可得φ(i)=i-1
}
for(int j=1;j<=tot;j++){
//枚举我们现在已经筛出的tot个质数
if(prime[j]>v[i]||i*prime[j]>N)
break;
//i有比prime[j]更小的质因子或者超出n的范围就退出
v[i*prime[j]]=prime[j];
//prime[j]就是合数i*prime[j]的最小质因子
if(!(i%prime[j])){//上述性质2
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else phi[i*prime[j]]=phi[i]*(prime[j]-1);
//上述性质3
}
}
}
下面是分解质因数的筛法
int phi(int n){
int ans=n;
for(int i=2;i*i<=n;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;
}
可以发现线性筛法适用于范围较小的数,而分解质因数法适用于求一个较大的数.
欧拉定理
直接给出欧拉定理(其实是有证明的):若正整数a,n互质,则(a^{φ(n)}≡1)(mod n),其中φ(n)为欧拉函数;
如果p是质数,则:根据上述推论1有(φ(p)=p-1),则(a^{p-1}≡1)(mod p),两边同乘a,又有(a^p≡a)(mod p)
于是就得到了费马小定理:若p是质数,则对于任意整数a,有(a^p≡a)(mod p)
欧拉定理的推论:若正整数a,n互质,则对于任意正整数b,有(a^b≡a^{b mod φ(n)})(mod n);
当a,n不一定互质且b>=φ(n)时,有(a^b≡a^{b mod φ(n)+φ(n)})(mod n)(这就是扩展欧拉定理)