费马小定理和例题 逆元的应用

本文介绍了费马小定理的基本概念及证明方法,并通过一个具体的编程问题展示如何利用该定理解决大数运算中的模运算问题。文章还提供了一段使用快速幂模运算实现费马小定理的应用代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

费马小定理:假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(mod p)。即:假如a是整数,p是质数,且a,p互质(即两者只有一个公约数1),那么a的(p-1)次方除以p的余数恒等于1。

同余证法:
任意取一个质数,比如13。考虑从1到12的一系列整数1,2,3,4,5,6,7,8,9,10,11,12,给这些数都乘上一个与13互质的数,比如3,得到3,6,9,12,15,18,21,24,27,30,33,36。对于模13来说,这些数同余于3,6,9,12,2,5,8,11,1,4,7,10。这些余数实际上就是原来的1,2,3,4,5,6,7,8,9,10,11,12,只是顺序不同而已。
把1,2,3,…,12统统乘起来,乘积就是12的阶乘12!。把3,6,9,…,36也统统乘起来,并且提出公因子3,乘积就是312×12!。对于模13来说,这两个乘积都同余于1,2,3,…,12系列,尽管顺序不是一一对应,即312×12!≡12!mod 13。两边同时除以12!得312≡1 mod 13。如果用p代替13,用x代替3,就得到费马小定理xp-1≡1 mod p。

 

C~K的难题 
Time Limit: 1000MS Memory Limit: 65536KB

Problem Description 
众所周知 C~K 喜欢数学,但是他最近被一个题给难住了,题目是这样的。 
要求 (A/B)%10007,但由于 A 很大,我们只给出 n (n = A%10007)(我们给定的A必能被B整除,且 gcd(B,10007) = 1)。 
你能帮助他解答吗?他会很感谢你的。

Input 
数据的第一行是一个 T,表示有 T 组数据。 
每组数据有两个数 n (0 <= n < 10007) 和 B (1 <= B <= 10^9)。

Output 
对应每组数据输出 (A/B)%10007。

Example Input 

1000 53 
87 123456789

Example Output 
8893 
7424

Hint

Author 
「山东理工大学第一届ACM知识挑战赛(机试)」C~K

以下为Accepted代码

#include <bits/stdc++.h>

using namespace std;

long long power_mod(long long a, long long k, long long mod)///快速乘
{
    long long ans = 1;
    while(k)
    {
        if(k & 1)///k是奇数
            ans = ans * a % mod;
        a = a * a % mod;
        k >>= 1;///k /= 2;
    }
    return ans;
}

const int mod = 10007;

int main()
{
    int T;
    long long n, b, x;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%lld %lld", &n, &b);
        x = power_mod(b, mod-2, mod);
        printf("%lld\n", n * x % mod);///费马小定理
    }
    return 0;
}
### 关于 Python 中逆元计算的示例代码 在 Python 中,可以通过多种方法计算乘法逆元。以下是基于费马小定理扩展欧几里得算法两种常见方式的具体实现。 #### 方法一:利用费马小定理 当模数 \( m \) 是素数时,可以根据费马小定理快速计算逆元。具体来说,对于给定的整数 \( a \),其在模 \( m \) 下的逆元等于 \( a^{m-2} \mod m \)[^1]。 ```python def mod_inverse_fermat(a, m): """ 使用费马小定理计算 a 在模 m 下的逆元 """ return pow(a, m - 2, m) # 测试案例 a = 3 m = 7 print(f"{a} 在模 {m} 下的逆元是: {mod_inverse_fermat(a, m)}") # 输出应为 5 ``` 此方法适用于模数 \( m \) 为素数的情况。 --- #### 方法二:使用扩展欧几里得算法 如果模数 \( m \) 不一定是素数,则可以采用扩展欧几里得算法来求解逆元。该算法的核心在于找到满足方程 \( ax + my = \gcd(a, m) \) 的整数 \( x \) \( y \)[^3]。只有当 \( \gcd(a, m) = 1 \) 时,\( x \) 才能作为 \( a \) 的逆元。 下面是具体的实现: ```python from math import gcd def extended_gcd(a, b): """ 扩展欧几里得算法,返回 (g, x, y) 满足 g = gcd(a, b), ax + by = g """ if b == 0: return (a, 1, 0) else: g, x, y = extended_gcd(b, a % b) return (g, y, x - (a // b) * y) def mod_inverse_extended_euclid(a, m): """ 使用扩展欧几里得算法计算 a 在模 m 下的逆元 """ g, x, _ = extended_gcd(a, m) if g != 1: raise ValueError("Inverse does not exist because gcd(a, m) is not 1.") else: return x % m # 测试案例 try: a = 3 m = 8 inv = mod_inverse_extended_euclid(a, m) print(f"{a} 在模 {m} 下的逆元是: {inv}") # 输出应为 3 except ValueError as e: print(e) ``` 这种方法更加通用,能够处理模数不是素数的情形。 --- ### 性能对比与适用场景 - **费马小定理**:适合用于模数为大素数的情况下,尤其是密码学领域中的应用。 - **扩展欧几里得算法**:更灵活,可应用于任意正整数模数,前提是 \( \gcd(a, m) = 1 \)。 上述两段代码分别展示了不同条件下的逆元计算逻辑,开发者可根据实际需求选择合适的方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值