【数论】——欧拉函数

332 阅读2分钟

【数论】——欧拉函数

定义

  • 定义 ϕ(n)\phi(n) 表示 [1,n] 中与 n 互质的数的个数。 由算术基本定理可得:
ϕ(n)=np11p1p21p2...pn1pn\phi(n) = n\cdot\frac{{p_1}-1}{p_1} \cdot \frac{{p_2}-1}{p_2}\cdot...\cdot\frac{{p_n}-1}{p_n}
ϕ(n)=npn(11p)(p为质数)\phi(n) = n\cdot \prod_{\frac{p}{n}}^{}{\left( 1-\frac{1}{p} \right)}(p 为质数)
  • 证明 设 p1,p2...pmp_1,p_2...p_mn 的质因子,则易知,对于任意 pip_i , 其倍数有 : 2pi,3pi...npi 2p_i,3p_i...\frac{n}{p_i} 当 n 有多个质数时,遵循容斥原理,约数个数为:
N(Np1+Np2+...+Npm)+(Np1p2+Np1p3+...+Npm1pm)+......+(1)m+1Np1p2...pm1pm)N-(\frac{N}{p_1}+\frac{N}{p_2}+...+\frac{N}{p_m})+(\frac{N}{p_1*p_2}+\frac{N}{p_1*p_3}+...+\frac{N}{p_{m-1}*p_m})+......+\left( -1 \right)^{m+1}*\frac{N}{p_1*p_2*...*p_{m-1}*p_m})

合并化简后:

ϕ(n)=npn(11p)(p为质数)\phi(n) = n\cdot \prod_{\frac{p}{n}}^{}{\left( 1-\frac{1}{p} \right)}(p 为质数)

欧拉函数的性质及推论(证明结合算术基本定理即可证明)

  1. 对于x大于1,区间**[1,x]中与n**互质的数的和为:
nϕ(n)2\frac{n*\phi(n)}{2}
  1. a,b互质,则有:
ϕ(ab)=ϕ(a)ϕ(b)\phi(a*b) = \phi(a)*\phi(b)

求解某数的欧拉函数

分解质因数法

  • 由于 ϕ(n)\phi(n) 表示 [1,n] 中与 n 互质的数的个数,因此只需要对 n 进行质因数分解再带入公式即可求出 ϕ(n)\phi(n)
  • 代码
int get_phi(int x)
{
    int ans = x;
    for (int i = 2; i <= x / i; i++) {if(n%i ==){x = ans / i * (i - 1);// 利用公式(pi-1)/pi
            while(x%i == 0)
                x /= i;
        }
    }
    if(x>1) // 此时的 x 为 x 的最大质因数
        ans = ans / x * (x + 1);
    return res;
}

求解区间内所有数的欧拉函数

线性筛法求欧拉函数

  • 筛法原理 基于线性筛质数原理(让每一个合数被最小的质数筛去),因此可以用一个递推,从 phi[i],推到,phi[i*primes[j]]
  • 分类讨论:
  1. 如果 p 是质数,则与 [2,p-1] 所有都互质,即 phi(p) = p-1;
  2. 如果p不是质数:遍历所有质数的倍数,递推见下方代码中注释
  • 复杂度分析: 加上break优化后,为O(n)
  • 代码(注释是重点)
bool st[N];
int primes[N], cnt;
int phi[N];
void get_phis(int x)
{
        for (int i = 2; i <= n; i++) {if (!st[i]) {primes[++cnt] = i;
            phi[i] = i - 1;// 定义出发,如果 p 是质数,则与 [2,p-1] 所有都互质,即 phi(p) = p-1
        }
        for (int j = 1; primes[j] <= n / i; j++) {st[primes[j] * i] = true;
            if (i % primes[j] == 0 {//primes[j]是 i 的一个质因子
                //phi[i]中已经乘了(primes[j]-1)/primes[j]
                //phi[primes[j]*i]和 phi[i]的差别在于最前面的 N 上,因此多乘一个 primes[j]保证 N 相同即可
                phi[primes[j] * i] = phi[i] * primes[j];
                
                break;
            }
            // 如果 primes[j]不是 i 的一个质因子,就要多乘一个(primes[j]-1)/primes[j],再乘一个 primes[j]保证 N 相同
            // 化简后分母消去,仅剩(primes[j] - 1
            phi[primes[j] * i] = phi[i] * (primes[j] - 1);}
    }
}