首页 > 代码库 > 解模逆元? x

解模逆元? x

逆元:

丢线

对于正整数技术分享技术分享,如果有技术分享,那么把这个同余方程中技术分享的最小正整数解叫做技术分享技术分享的逆元。

 

逆元一般用扩展欧几里得算法来求得,如果技术分享为素数,那么还可以根据费马小定理得到逆元为技术分享

 

推导过程如下

                            技术分享

 

求现在来看一个逆元最常见问题,求如下表达式的值(已知技术分享)(|为整除号)

 

         技术分享  

 

当然这个经典的问题有很多方法,最常见的就是扩展欧几里得,如果技术分享是素数,还可以用费马小定理!!!

 

但是你会发现费马小定理和扩展欧几里得算法求逆元是有局限性的,它们都会要求技术分享技术分享互素。实际上我们还有一种通用的求逆元方法,适合所有情况。

公式如下:

 

          技术分享

 

现在我们来证明它,已知技术分享,证明步骤如下

 

          技术分享

 

而对于(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));}

 

解模逆元? x