【算法】 欧拉函数与欧拉降幂 python

发布于:2025-04-13 ⋅ 阅读:(17) ⋅ 点赞:(0)

欧拉函数


欧拉函数 ϕ ( n ) \phi(n) ϕ(n) 表示小于等于 n 的正整数中与 n 互质的数的个数。即:

ϕ ( n ) = ∣ { k ∈ Z + ∣ 1 ≤ k ≤ n , gcd ⁡ ( k , n ) = 1 } ∣ \phi(n) = \left| \{ k \in \mathbb{Z}^+ \mid 1 \leq k \leq n, \gcd(k, n) = 1 \} \right| ϕ(n)={kZ+1kn,gcd(k,n)=1}

当  n  是质数的时候,显然有  φ ( n ) = n − 1 。 \text{当 }n\text{ 是质数的时候,显然有 }\varphi(n)=n-1\text{。}  n 是质数的时候,显然有 φ(n)=n1

 若  n = p k ,其中  p  是质数,那么  φ ( n ) = p k − p k − 1 。 \text{ 若 }n=p^k\text{,其中 }p\text{ 是质数,那么 }\varphi(n)=p^k-p^{k-1}。   n=pk,其中 p 是质数,那么 φ(n)=pkpk1


求一个数的欧拉函数值,在质因数分解的同时求:

from math import isqrt  
def euler_phi(n):  
    if n == 1:  
        return 1  
    else:  
        phi = n  
        max_n = isqrt(n)  
        for i in range(2, max_n + 1):  
            if n % i == 0:  
                phi -= phi // i  
                while n % i == 0:  
                    n //= i  
        if n > 1:  
            phi -= phi // n  
        return phi

筛法求欧拉函数:

def euler_phi_sieve(n):
    phi = list(range(n + 1))  # 初始化phi[i] = i
    for i in range(2, n + 1):
        if phi[i] == i:
            for j in range(i, n + 1, i):  # 遇到质数i 调整i所有倍数的欧拉函数值
                phi[j] -= phi[j] // i
    return phi


https://www.acwing.com/problem/content/description/4002/

d = gcd(a,m) = gcd(a+x,m)
d|a d|(a+x) --> d|x
我们定义  a ′ = a d , m ′ = m d , x ′ = x d ,那么根据最大公约数的性质,可得: gcd ⁡ ( a ′ + x ′ , m ′ ) = 1 \begin{aligned}\text{我们定义 }a^{\prime}=\frac ad,m^{\prime}=\frac md,x^{\prime}=\frac xd\text{,那么根据最大公约数的性质,可得:}\gcd(a^{\prime}+x^{\prime},m^{\prime})=1\end{aligned} 我们定义 a=da,m=dm,x=dx,那么根据最大公约数的性质,可得:gcd(a+x,m)=1
而题目就转化为了: 求  [ a ′ , a ′ + m ′ − 1 ]  中有几个数与  m ′  互质。 \text{而题目就转化为了: 求 }[a^{\prime},a^{\prime}+m^{\prime}-1]\text{ 中有几个数与 }m^{\prime}\text{ 互质。} 而题目就转化为了 [a,a+m1] 中有几个数与 m 互质。
因为  [ 0 , a ′ − 1 ]  中在模  m  的意义下的余数与  [ m ′ , a ′ + m ′ − 1 ]  一样 \text{因为 }[0,a^{\prime}-1]\text{ 中在模 }m\text{ 的意义下的余数与 }[m^{\prime},a^{\prime}+m^{\prime}-1]\text{ 一样} 因为 [0,a1] 中在模 m 的意义下的余数与 [m,a+m1] 一样

所以转化为求 p h i ( m ′ ) phi(m') phi(m)

from math import isqrt, gcd
def euler_phi(n):
    if n == 1:
        return 1
    phi = n
    for i in range(2, isqrt(n) + 1):
        if n % i == 0:
            phi -= phi // i
            while n % i == 0:
                n //= i
    if n > 1:
        phi -= phi // n
    return phi

t = int(input())
for _ in range(t):
    a, m = map(int, input().split())
    d = gcd(a, m)
    ans = euler_phi(m // d)
    print(ans)


https://www.acwing.com/problem/content/203/

本题 n ,t 数据范围较小 --> 不然需要 筛法求欧拉函数 , 甚至加上前缀和优化

from math import isqrt
def euler_phi(n):
    if n == 1:
        return 1
    phi = n
    for i in range(2, isqrt(n) + 1):
        if n % i == 0:
            phi -= phi // i
            while n % i == 0:
                n //= i
    if n > 1:
        phi -= phi // n
    return phi

t = int(input())
for i in range(1, t + 1):
    n = int(input())
    cnt = 0
    for k in range(n + 1):
        cnt += euler_phi(k)
    ans = cnt * 2 + 1
    print(f"{i} {n} {ans}")


2023蓝桥杯省赛

https://www.lanqiao.cn/problems/3522/learning/

若m和n的质因数组成相同,m是n的k倍,则euler_phi(m)也是euler_phi(n)的k倍
euler_phi(a^b) = euler_phi(a) * a^(b-1)

mod = 998244353
a, b = map(int, input().split())
if a == 1:
    exit(print(0))

from math import isqrt
def euler_phi(n):
    if n == 1:
        return 1
    phi = n
    max_n = isqrt(n)
    for i in range(2, max_n + 1):
        if n % i == 0:
            phi -= phi // i
            while n % i == 0:
                n //= i
    if n > 1:
        phi -= phi // n
    return phi

print(pow(a, b - 1, mod) * euler_phi(a) % mod)


欧拉降幂

幂次大于欧拉函数值 --> 欧拉降幂

a b ≡ { a b   m o d   φ ( m ) , gcd ⁡ ( a , m ) = 1 , a b , gcd ⁡ ( a , m ) ≠ 1 , b < φ ( m ) , ( m o d   m ) a ( b   m o d   φ ( m ) ) + φ ( m ) , gcd ⁡ ( a , m ) ≠ 1 , b ≥ φ ( m ) . a^b\equiv\begin{cases}a^{b\mathrm{~mod~}\varphi(m)},&\gcd(a,m)=1,\\a^b,&\gcd(a,m)\neq1,b<\varphi(m),&(\mathrm{mod~}m)\\a^{(b\mathrm{~mod~}\varphi(m))+\varphi(m)},&\gcd(a,m)\neq1,b\geq\varphi(m).&\end{cases} ab ab mod φ(m),ab,a(b mod φ(m))+φ(m),gcd(a,m)=1,gcd(a,m)=1,b<φ(m),gcd(a,m)=1,bφ(m).(mod m)


模板

https://www.luogu.com.cn/problem/P5091

a, m, b = input().split()  # 读取为字符串(b非常大)
a = int(a)
m = int(m)

from math import isqrt, gcd
def euler_phi(n):
    if n == 1:
        return 1
    max_n = isqrt(n)
    phi = n
    for i in range(2, max_n + 1):
        if n % i == 0:
            phi -= phi // i
            while n % i == 0:
                n //= i
    if n > 1:
        phi -= phi // n
    return phi

if m == 1:
    exit(print(0))

phi = euler_phi(m)
flg = 0
b_mod_phi = 0
for digit in b:
    b_mod_phi = (b_mod_phi * 10 + int(digit)) % phi

if len(b) > len(str(phi)):
    flg = 1
elif len(b) == len(str(phi)):
    flg = b >= str(phi)

if gcd(a, m) == 1:
    int_b = b_mod_phi
else:
    if flg:
        int_b = b_mod_phi + phi
    else:
        int_b = int(b)

print(pow(a, int_b, m))


https://www.lanqiao.cn/problems/1155/learning/

n, m = map(int, input().split())
mod = 10**9 + 7
phi = mod - 1

x = 1
flg = 0
for i in range(1, m + 1):
    x *= i
    if x >= phi:
        x %= phi
        flg = 1
if flg:
    x += phi

print(pow(n, x, mod))


END
*如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给


网站公告

今日签到

点亮在社区的每一天
去签到