欧拉函数(Euler’s totient function),求小于或者等于 n n n的数中与 n n n互质的数的个数,记为: φ ( n ) \varphi(n) φ(n)。
欧拉函数的通式 φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) … ( 1 − 1 p n ) \varphi \left( n\right) =n\left( 1-\dfrac {1} {p_{1}}\right) \left( 1-\dfrac {1} {p_{2}}\right) \ldots \left( 1-\dfrac {1} {p_{n}}\right) φ(n)=n(1−p11)(1−p21)…(1−pn1),其中 p 1 , p 2 , … , P n p_1,p_2,\dots,P_n p1,p2,…,Pn都是 n n n的质因数。
比如: φ ( 1 ) = 1 \varphi(1)=1 φ(1)=1。
当 n n n时质数的时候,显然有 φ ( n ) = n − 1 \varphi(n)=n-1 φ(n)=n−1。
欧拉定理:若 a , n a,n a,n为正整数, g c d ( a , n ) = 1 gcd(a,n)=1 gcd(a,n)=1,则 a φ ( n ) Ξ 1 ( m o d n ) a^{\varphi(n)} \Xi \:1(mod\:n) aφ(n)Ξ1(modn)。
若 n n n是质数,则 φ ( n ) = n − 1 \varphi(n)=n-1 φ(n)=n−1。
若 n n n是合数,则 φ ( n ) \varphi(n) φ(n)自己算去吧!!!
欧拉函数是积性函数:
若 n , m n,m n,m互质,则 φ ( n × m ) = φ ( n ) × φ ( m ) \varphi(n\times m)=\varphi(n)\times \varphi(m) φ(n×m)=φ(n)×φ(m)。
当 n n n为奇数时,有 φ ( 2 × n ) = φ ( n ) \varphi(2\times n)=\varphi(n) φ(2×n)=φ(n)。
若 n = p k n=p^k n=pk且 P P P是质数,则 φ ( n ) = p k − p k − 1 \varphi(n)=p^k-p^{k-1} φ(n)=pk−pk−1。
除了 n = 2 n=2 n=2, φ ( n ) \varphi(n) φ(n)都是偶数。
在这里,我们先求一个数的欧拉函数值,这样我们可以直接根据定义质因数分解的同时求解。时间复杂度为 O ( N ) O(N) O(N)。
int oula(int n){
int res = n;
for(int i = 2; i * i <= n; i++){//n的素因子定在sqrt(n)内
if(n % i == 0){
res = res - res / i;//res = res - res / i是由n*(1-1/i)化来的,在这里不允许有小数,都是整数运算
while(n % i == 0) n /= i;
}
}
if(n > 1) res = res - res / n;
return res;
}
那么对于多个数的欧拉函数值,我们是是否可以进行线性筛选呢?答案是可以的。
φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) … ( 1 − 1 p n ) \varphi \left( n\right) =n\left( 1-\dfrac {1} {p_{1}}\right) \left( 1-\dfrac {1} {p_{2}}\right) \ldots \left( 1-\dfrac {1} {p_{n}}\right) φ(n)=n(1−p11)(1−p21)…(1−pn1),其中 p 1 , p 2 , … , P n p_1,p_2,\dots,P_n p1,p2,…,Pn都是 n n n的质因数。
例如: φ ( 12 ) = 12 × ( 1 − 1 2 ) × ( 1 − 1 3 ) = 4 \varphi(12)=12\times(1-\frac{1}{2})\times(1-\frac{1}{3})=4 φ(12)=12×(1−21)×(1−31)=4.
利用这个我们可以类似求素数的的筛法。先筛出N以内的所有素数,再以素数筛每个数的φ值。
比如求8以内所有数的φ值:设一个数组 p h i [ 9 ] phi[9] phi[9],初始值为 p h i [ 1 ] = 1 , p h i [ 2 ] = 2 , … , p h i [ 8 ] = 8 phi[1]=1,phi[2]=2,\dots,phi[8]=8 phi[1]=1,phi[2]=2,…,phi[8]=8,然后从 2 2 2开始循环,把 2 2 2的倍数的 φ \varphi φ值都乘以 ( 1 − 1 2 ) (1-\frac{1}{2}) (1−21);再是把 3 3 3的倍数的 φ \varphi φ值都乘以 ( 1 − 1 3 ) … (1-\frac{1}{3})\dots (1−31)…。(这里有点运用了素数的埃氏筛选的思想)。对于每一个素数都进行如此操作,就相当于任何一个 n n n都进行了 φ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) … ( 1 − 1 p n ) \varphi \left( n\right) =n\left( 1-\dfrac {1} {p_{1}}\right) \left( 1-\dfrac {1} {p_{2}}\right) \ldots \left( 1-\dfrac {1} {p_{n}}\right) φ(n)=n(1−p11)(1−p21)…(1−pn1)的运算。
const int MAXN = 2e5 + 10;
int oula[MAXN];
void Inou(){
for(int i = 1; i <= MAXN; i++){
oula[i] = i;
}
for(int i = 2; i <= MAXN; i++){
if(oula[i] == i){//素数在之前是不会被任何数筛的
for(int j = i; j <= MAXN; j += i){
oula[j] = oula[j] - oula[j] / i;
}
}
}
}
如果以上内容有错误的地方,请在下面评论指出,谢谢了!!!