【数论】——欧拉函数

【数论】——欧拉函数

定义

  • 定义 ϕ ( n ) \phi(n) ϕ(n) 表示 [1,n] 中与 n 互质的数的个数。
    由算术基本定理可得:
    ϕ ( n ) = n ⋅ p 1 − 1 p 1 ⋅ p 2 − 1 p 2 ⋅ . . . ⋅ p n − 1 p n \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)=np1p11p2p21...pnpn1
    ϕ ( n ) = n ⋅ ∏ p n ( 1 − 1 p ) ( p 为 质 数 ) \phi(n) = n\cdot \prod_{\frac{p}{n}}^{}{\left( 1-\frac{1}{p} \right)}(p 为质数) ϕ(n)=nnp(1p1)(p)
  • 证明

    p 1 , p 2 . . . p m p_1,p_2...p_m p1,p2...pm
    n 的质因子,则易知,对于任意 p i p_i pi , 其倍数有 :
    2 p i , 3 p i . . . n p i 2p_i,3p_i...\frac{n}{p_i} 2pi,3pi...pin
    当 n 有多个质数时,遵循容斥原理,约数个数为:
    N − ( N p 1 + N p 2 + . . . + N p m ) + ( N p 1 ∗ p 2 + N p 1 ∗ p 3 + . . . + N p m − 1 ∗ p m ) + . . . . . . + ( − 1 ) m + 1 ∗ N p 1 ∗ p 2 ∗ . . . ∗ p m − 1 ∗ p m ) 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(p1N+p2N+...+pmN)+(p1p2N+p1p3N+...+pm1pmN)+......+(1)m+1p1p2...pm1pmN)
    合并化简后:
    ϕ ( n ) = n ⋅ ∏ p n ( 1 − 1 p ) ( p 为 质 数 ) \phi(n) = n\cdot \prod_{\frac{p}{n}}^{}{\left( 1-\frac{1}{p} \right)}(p 为质数) ϕ(n)=nnp(1p1)(p)

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

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

求解某数的欧拉函数

分解质因数法

  • 由于 ϕ ( n ) \phi(n) ϕ(n) 表示 [1,n] 中与 n 互质的数的个数,因此只需要对 n 进行质因数分解再带入公式即可求出 ϕ ( n ) \phi(n) ϕ(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);}
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Siriu_Sky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值