分数(小数)取模 利用逆元 python

本文介绍了如何在Python中利用费马小定理和扩展欧几里得算法解决分数取模问题,如4/3对1000000007取模,得到333333337的结果。

在腾讯的一次笔试中,要求对分数取模 4/3 对1000000007 取余结果是333333337

1. 利用费马小定理

# 计算 x的y次方 对mod取模
def power(x, y, mod):
    r = 1
    while( y ):
        if y & 1:
            r = (r * x) % mod
        x = (x * x) % mod
        y >>= 1

    return r

x = 3
y = 2
# mod = 100000000 + 7
# 利用费马小定理求与(分母)逆元
mod = 7
inv = power(y, mod - 2, mod)
# 再求x分子乘以逆元取模
ans = x * inv % mod
print(ans )

程序中求的是 二分之三     (3/2)  对 7 的取模结果

 

2. 利用扩展欧几里得算法

 

# 扩展欧几里得算法(求乘法逆元)
def ex_gcd(dividend, divisor):
    if 0 == divisor:
        # 易证明:当除数等于0时,可得 X = 1,
在数论和密码学中,对分数进行运算通常需要将分数转换为整数运算,这可以通过使用**逆元**来实现。逆元运算中起到类似“倒数”的作用,从而使得分数运算可以转换为整数运算。 ### 分数的基本原理 对于一个分数 $ \frac{a}{b} $,如果要在 $ p $ 下进行运算,通常会将其转换为 $ a \times b^{-1} \mod p $,其中 $ b^{-1} $ 是 $ b $ 关于 $ p $ 的逆元逆元的定义是满足 $ b \times b^{-1} \equiv 1 \mod p $ 的整数 $ b^{-1} $。[^3] ### 如何求逆元 1. **遍历法**:可以通过遍历从 0 到 $ p-1 $ 的所有整数,找到满足 $ (b \times i) \mod p = 1 $ 的整数 $ i $,该 $ i $ 即为 $ b $ 的逆元。[^1] 2. **扩展欧几里得算法**:通过扩展欧几里得算法(ex_gcd)可以高效地计算逆元。如果 $ \gcd(a, p) = 1 $,那么 $ a $ 存在逆元,可以通过以下代码计算: ```python def inv(a, p): g, x, y = ex_gcd(a, p) if g != 1: return 0 # 表示整数a没有逆元 return x % p ``` 其中 `ex_gcd` 是扩展欧几里得算法的实现。[^3] ### 分数的实现步骤 1. **化简分数**:将分数 $ \frac{a}{b} $ 化简为最简形式,确保分子和分母互质。 2. **求逆元**:计算分母 $ b $ 关于 $ p $ 的逆元 $ b^{-1} $。 3. **运算**:将分数转换为 $ a \times b^{-1} \mod p $。 ### 示例:分数运算 假设需要计算 $ \frac{2}{5} \mod 10 $,步骤如下: 1. 计算 $ 5 $ 关于 $ 10 $ 的逆元。由于 $ \gcd(5, 10) \neq 1 $,5 没有逆元,因此 $ \frac{2}{5} \mod 10 $ 无法直接计算。 2. 如果数为 7,那么 $ 5 $ 关于 $ 7 $ 的逆元是 $ 3 $,因为 $ 5 \times 3 \equiv 1 \mod 7 $。 3. 因此 $ \frac{2}{5} \mod 7 $ 可以计算为 $ 2 \times 3 \mod 7 = 6 $。 ### 结构化分数表示 在程序中,可以使用结构体存储分数的分子和分母,并确保分数化简为最简形式: ```c struct Fraction { int up, down; }; ``` 化简分数时需要确保分母为正整数,并且分子和分母的最大公约数为 1。[^4] ### 分数的注意事项 - 如果分母 $ b $ 和数 $ p $ 不互质(即 $ \gcd(b, p) \neq 1 $),则无法计算逆元分数无解。 - 在密码学中,通常使用大素数作为数,这样可以确保大多数数存在逆元。 ### 示例代码 以下是使用扩展欧几里得算法计算逆元Python 实现: ```python def ex_gcd(a, b): if b == 0: return (a, 1, 0) else: g, x, y = ex_gcd(b, a % b) return (g, y, x - (a // b) * y) def inv(a, p): g, x, y = ex_gcd(a, p) if g != 1: return 0 # 表示整数a没有逆元 return x % p ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值