介绍
在数论中,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler's totient function),它又称为Euler's totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。
我们常用(phi(p))来表示(p)的欧拉函数值.
计算通式
欧拉函数的通式为:
[phi(x) = x*(1-frac{1}{p1})*(1-frac{1}{p2})*(1-frac{1}{p3})* ... *(1-frac{1}{p_n})
]
其中(p_i)表示(x)的质因数。特别声明,(phi(1)=1)。
性质
- 如果(p)是质数
- (phi(p)=p-1)
- 若(i) mod (p=0), 那么(phi(i*p)=p*phi(i))
- 若(i) mod (p≠0), 那么(phi(i*p)=phi(i)*(p-1))
- 所有情况通用
- (phi(p^k) = p^k-p^{k-1}=(p-1)*p^{k-1})
简单的证明(对应上面每一条性质):
- 显然,因为 (p)为质数,所以与它前面的(p-1)个数都互质.
- 引用自Lytning's Blog
- 因为(i) mod (p ≠0),而欧拉函数是积性函数,至于为什么是积性函数(反正积性函数这东西知道就好了,没必要会证明)可以看看这篇博客,所以(phi(i * p)=phi(i)*phi(p)=phi(i)*(p-1))
- 令(n=p^k),小于 n 的正整数共有(p^{k-1})个,其中与 p 不互素的个数共(p^{k-1}-1)个,它们是(1*p,2*p,3*p ... (p^{k-1}-1)*p)所以(phi(p^k) = (p^k-1)-(p^{k-1}-1)=p^k-p^{k-1}=(p-1)*p^{k-1}).(引用自angel_imp)
如何代码实现线性筛
这里我们需要用到前三条性质,并在筛素数的同时筛出欧拉函数.直接看代码注释吧.
#include<bits/stdc++.h>
using namespace std;
const int N=40000+5;
int n;
int prime[N];//存素数表
int size = 0;//素数表大小
int phi[N];//存欧拉函数值
bool is_prime[N];//是否为素数
void get_phi(int lim){
memset(is_prime,1,sizeof(is_prime));
is_prime[0] = is_prime[1] = false;
phi[1] = 1;
for(int i=2;i<=lim;i++){
if(is_prime[i])
prime[++size] = i, phi[i] = i-1;//性质1
for(int j=1;j<=size && i*prime[j] <= lim;j++){
is_prime[i*prime[j]] = 0;//筛素数的过程
if(i % prime[j] == 0){phi[i*prime[j]] = phi[i]*prime[j];break;}//性质2
else phi[i*prime[j]] = phi[i]*(prime[j]-1);//性质3
}
}
}
int main(){
cin >> n;
get_phi(n);
return 0;
}
如何在(sqrt{n})的时间复杂度内求出(phi(n))
其实就直接利用欧拉函数的计算通式来计算就可以了.复杂度来自与(sqrt{n})的因式分解.
int Phi(int x){
for(int i=1;i<=size && prime[i] <= x;i++)
if(x % prime[i] == 0) x = x/prime[i]*(prime[i]-1);
return x;
}
拓展欧拉定理
对于任意 (b geq varphi(p)) ,有:
[a^bequiv a^{bmod varphi(p)+varphi(p)}pmod{p}
]
当(b<varphi(p))时有 (a^bequiv a^{bmod varphi(p)}pmod{p}).
其中 (a,p) 可以不互质.
证明
可以看看ez_yww的博客 (我也不太会..).