费马小定理求逆元

逆元:已知P为质数,且gcd(A,P)==1,  A*B在同模P的情况下与1相等 求出B的值

即 A*B=1(在mod P的条件下)所以乘B即乘以A^-1 ,B就是A的逆元

费马小定理:P为质数时且gcd(A,P)==1,则A^(P-1)=1(在mod P的条件下)

证明我不会qwq

所以根据费马小定理  A*B=A^(P-1) 所以B=A^(P-2)

根据上述就可以轻松得到   A当P为质数且gcd(A,P)==1时的逆元

例题:洛谷3381的模板题(用费马小定理只能得到83,会TLE一个点)

题目描述

给定n,p求1~n中所有整数在模p意义下的乘法逆元。

输入输出格式

输入格式:

一行n,p

输出格式:

n行,第i行表示i在模p意义下的逆元。

因为P为质数且A<P,所以gcd(A,P)==1   即求A*x=1((在mod P的条件下) 中的x

//费马小定理求逆元 
#include<bits/stdc++.h>
using namespace std;
int n,Mod;
inline int Pow(int x,int y,int p){
	int res=1;
	while(y){
		if(y&1)
			res=(1LL*res*x)%p;
		y>>=1;
		x=(1LL*x*x)%p;
	}return res;
}//快速幂
int main(){
	scanf("%d%d",&n,&Mod);
	for(int i=1;i<=n;i++){
		printf("%d\n",Pow(i,Mod-2,Mod));//直接输出i^(Mod-2)%Mod,是不是很方便
	}
}


### 关于逆元的例题及解答 #### 例题一:给定整数 $ a = 7, m = 13 $,求 $ a $ 在模 $ m $ 下的乘法逆元。 如果存在这样的 $ b $ 满足条件 $ ab \equiv 1 \ (\text{mod} \ m) $ 并且 $\gcd(a, m) = 1$,那么可以通过扩展欧几里得算法或者快速幂的方法找到这个 $ b $ 的值[^1]。 ##### 解答: 由于 $ gcd(7, 13) = 1 $,可以确认该逆元确实存在。下面通过两种方法分别解决此问题。 ###### 方法一:扩展欧几里得算法 利用贝祖等式 $ ax + my = \gcd(a, m) $ 来找出满足条件的一个特解 $(x_0, y_0)$ 。对于本题目中的数据代入得到具体过程如下所示: $$ \begin{aligned} &13 = 1 * 7 + 6 \\ &7 = 1 * 6 + 1 \\ &6 = 6 * 1 + 0. \end{aligned} $$ 回带可得 $ 1 = 7 - 1*(13-1*7)=2*7-1*13 $. 故取正余数部分即为所求数字 $ b=2 $. 最终答案为 $ b = 2 $ [^2]. ###### 方法二:费马小定理(当 $ m $ 是素数时) 因为 $ m = 13 $ 是一个质数,并且已知 $ gcd(7, 13) = 1 $ ,所以可以直接应用费马小定理得出结论 $ 7^{11} \mod 13 $ 即为我们所需要的数值[^3]。 代码实现如下: ```cpp #include <bits/stdc++.h> using namespace std; int fast_pow(int base, int exp, int mod){ long long result = 1; while(exp > 0){ if(exp % 2 ==1 ){ result = (result *base )%mod ; } base =(long long)(base *base)%mod; exp /=2; } return result; } int main(){ int a=7 ,m=13; cout<<fast_pow(a,m-2,m)<<endl; } ``` 运行上述程序会输出 `2` 表明结果一致。 --- #### 例题二:给出一组测试样例输入并验证其正确性。 假设现在有多个组的数据需要处理,请编写完整的 C++ 程序完成批量运算功能。 ##### 输入描述: 多组测试案例每行为两个整数表示 $ a_i,\ m_i $ ##### 输出描述: 对应每一行输出对应的逆元;如果没有则打印 `-1`. ##### 示例输入/输出: Input: ``` 7 13 8 15 ``` Output: ``` 2 -1 ``` 完整解决方案见下述代码片段: ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; ll ex_gcd(ll a,ll b,ll &x,ll &y){ if(b==0){x=1;y=0;return a;} ll d=ex_gcd(b,a%b,y,x); y-=a/b*x; return d; } void solve(){ ios::sync_with_stdio(false); cin.tie(NULL); ll a,b,d,x,y; while(cin>>a>>b){ d=ex_gcd(a,b,x,y); if(d!=1 || x<0)x=-1; cout<<(x+b)%b<<"\n"; } } int main(){solve();return 0;} ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值