定义
在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)(\varphi(1)=1)(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler′stotientfunction)(Euler's totient function)(Euler′stotientfunction),它又称为Euler′stotientfunction、φEuler's totient function、\varphiEuler′stotientfunction、φ函数、欧拉商数等。 例如φ(8)=4\varphi(8)=4φ(8)=4,因为1,3,5,7均和8互质。——来自百度百科。
其实百度百科这次说的比较明白,就是1-n中与n互质的数的个数,我们用φ(n)\varphi(n)φ(n)来表示。
性质
以下性质和定理不涉及证明。
-
欧拉函数是积性函数。即:φ(nm)=φ(n)φ(m)\varphi(nm)=\varphi(n)\varphi(m)φ(nm)=φ(n)φ(m),其中gcd(n,m)=1gcd(n,m)=1gcd(n,m)=1。
-
当n为奇数时,φ(2n)=φ(n)\varphi(2n)=\varphi(n)φ(2n)=φ(n)
-
当n为质数时,φ(n)=n−1\varphi(n)=n-1φ(n)=n−1
-
φ(1)=1\varphi(1)=1φ(1)=1
-
欧拉定理:对于互质的正整数aaa和nnn,有aφ(n)≡1modna^\varphi(n) \equiv 1 mod naφ(n)≡1modn。因此此定理也用来求逆元。
-
若n=pkn=p^kn=pk,则φ(n)=(p−1)×pk−1\varphi(n)=(p-1)×p^{k-1}φ(n)=(p−1)×pk−1
-
设n=p1k1×p2k2×...×pmkmn=p1^{k1} × p2^{k2} × ... × pm^{km}n=p1k1×p2k2×...×pmkm,则φ(n)=n×(1−1p1)×(1−1p2)...×(1−1pm)\varphi(n)=n×(1-\frac{1}{p1})×(1-\frac{1}{p2})...×(1-\frac{1}{pm})φ(n)=n×(1−p11)×(1−p21)...×(1−pm1)
求法
其实求法的话,在性质里面基本都提到了,所以只提供几种针对不同题目的求法。
1.筛法
对于题目中要用到好多的欧拉函数的问题,我们需要提前预处理出每一个数的欧拉函数,然后在O(1)O(1)O(1)时间内回答。
筛法主要是修改自线性素数筛,结合欧拉函数的性质就能筛出欧拉函数。
代码实现:
void phi() {
for(int i=2; i<=n; i++) {
if(!vis[i]) {
prime[++top] = i;
phi[i] = i-1;
}
for(int j=1; j<=top&&i*prime[j]<=n; j++) {
vis[i*prime[j]] = 1;
if(i%prime[j]==0) {
phi[i*prime[j]] = prime[j]*phi[i];
break;
} else
phi[i*prime[j]] = phi[i]*phi[prime[j]];
}
}
}
2.单个求
有的题目比较良心,只让你求一个数的欧拉函数,但是不太良心的是这个数特别大。所以我们考虑怎么求一个大数的欧拉函数。
首先,可以O((n))O(\sqrt(n))O((n))的时间内判断一个数是否为质数,由欧拉函数的性质我们就可以知道质数的欧拉函数就是本身减一。如果不是质数,那么我们就用欧拉函数的计算公式:性质7。
对于一个数,我们没必要把质数表打出来,只需要O((n))O(\sqrt(n))O((n))的时间内枚举质数就好,然后不断的whilewhilewhile判断下去,期望的时间复杂度为O((n)logn)O(\sqrt(n)logn)O((n)logn)
代码实现
unsigned long long phi(unsigned long long x) {
double ans = x;
for(unsigned long long i=1; i<=top; i++) {
if(x%prime[i])
continue;
while(x%prime[i]==0)
x /= prime[i];
ans = ans * (1-1.0/prime[i]);
}
return ans;
}
后记
欧拉函数还是比较重要的,在做题的时候如果发现找规律的话,就耐心的找一下。
不过最重要的还是要对数字敏感,体现在欧拉函数上就是,看到输入质数,输出减一的,应自然而然的联想到欧拉函数。