逆元:
对于正整数和,如果有,那么把这个同余方程中的最小正整数解叫做模的逆元。
逆元一般用扩展欧几里得算法来求得,如果为素数,那么还可以根据费马小定理得到逆元为。
推导过程如下
求现在来看一个逆元最常见问题,求如下表达式的值(已知)(|为整除号)
当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果是素数,还可以用费马小定理!!!
但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求与互素。实际上我们还有一种通用的求逆元方法,适合所有情况。
公式如下:
现在我们来证明它,已知,证明步骤如下
而对于(a/b)%m== 一个数
1.当m是素数的时候,根据费马小定理(不懂的可以去这儿看看),直接输出b^(n-2)即可
2.否则,就根据扩展欧几里得exgcd(b,m,x,y)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; int a,b,m; int x,y; int exgcd(int a,int b,int &x,int &y) { if(b==0) { x=1; y=0; return a; } int r=exgcd(b,a%b,x,y),tmp; tmp=x,x=y; y=tmp-a/b*y; return r; } int fastpow(int a,int p) { int bb=a;int ans=1; while(p!=0) { if(p%2==1)ans=ans*bb; bb=bb*bb; p=p/2; } return ans; } int main() { scanf("%d%d%d",&a,&b,&m); for(int i=1;i<=sqrt(m);i++) { if(m%i==0) { int ans=exgcd(b,m,x,y); printf("%d",(a*ans)%m); return 0; } } printf("%d",fastpow(b,m-2)); }
时间: 2024-11-03 20:44:51