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


欧拉函数


欧拉函数 ϕ ( 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
*如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给

欧拉降幂是一种用于处理大指数取模运算的有效算法,在密码学等领域有广泛应用。直接计算大数的幂次再求模可能会导致溢出和性能问题,而通过欧拉定理可以简化这一过程。 ### 欧拉降幂的基本原理 对于两个正整数 \(a\) 和 \(m\) ,如果它们互质(即 \(\gcd(a,m) = 1\), 其中 gcd 表示最大公约数),那么可以根据欧拉定理: \[ a^{\phi(m)} ≡ 1 (\bmod m) \] 其中 φ(m) 是小于等于 m 的、 m 互素的自然数的数量(称为欧拉函数)。因此我们可以将原本复杂的高次幂转化为相对简单的低次幂来进行快速计算。 当底数\(a\)和模数\(m\)不一定互质的时候,则需要利用广义形式或者其他技巧如分治法来解决。 下面是基于Python语言的一个简单版本实现: ```python from math import gcd def euler_totient(n): """ 计算欧拉函数值 """ result = n # Initialize result as n p = 2 # Iterate through all prime factors. while p * p <= n: # Check if p is a prime factor. if n % p == 0: # If yes, then update n and result while n % p == 0: n //= p result -= result // p p += 1 if n > 1: # Special case for when the remaining number itself is also a prime greater than sqrt(original_n) result -= result // n return int(result) def modular_exponentiation(base, exp, mod): """ 快速幂取模算法 """ res = 1 base %= mod while exp > 0: if (exp & 1) != 0: res = (res * base) % mod exp >>= 1 base = (base * base) % mod return res def euler_power_modulo(a, b, m): phi_m = euler_totient(m) def reduce_exp(e): nonlocal phi_m e %= phi_m if not e or (e == phi_m and a%m==0): return phi_m else: return e reduced_b = reduce_exp(b - 1) + 1 ans = modular_exponentiation(a, reduced_b , m) print(f"{a}^{b} mod {m} =",ans) return ans # 测试例子 if __name__ == "__main__": a, b, m = map(int, input("请输入三个数字作为基础参数(空格分割):\n").split()) euler_power_modulo(a,b,m) ``` 这个程序实现了对给定的基础参数 `a`, 幂 `b` 及模 `m` 进行欧拉降幂操作,并打印结果。 请注意实际应用时还需要考虑更多边界情况以及效率优化等问题。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值