乘法逆元

来源:互联网 发布:spd7网络信号避雷器 编辑:程序博客网 时间:2024/05/16 04:01

概述

对于一个模方程ax1(mod m),x就是a的乘法逆元,记作a1
那么求a/b mod m的时候,求ab1 mod m$就行了。
ps:和模方程一样,当(a,m)|1(即(a,m)=1)的时候存在解,否则无解。

方法1

用扩展欧几里得算法即可求得x。

int exgcd(int a,int b,int &x,int &y){    if (!b) {x=1;y=0;return a;}    int r=exgcd(b,a%b,x,y),t=x;x=y;y=t-a/b*y;    return r;}int mul_INV(int a,int m){    int x,y;if (exgcd(a,m,x,y)!=1) return -1;    return (x%m+m)%m;}

方法2

一种递推的算法,可以O(p)推出1~p-1的逆元(算出INV[i]的前提是INV[i]存在),由于>p的逆元可以回到1~p-1,所以不用求。
首先111(mod p),设p=ai+r,则a=p/i,r=p mod i,放到mod p的意义下:
ai+r0(mod p)
同乘i1r1,得:
a(r1+i10(mod p)
i1ar1(mod p)
i1p/i(p mod i)(mod p)
所以说INV[i]=-(p/i)*INV[p%i]

方法3

根据费马小定理,当p为素数,a为正整数,gcd(a,p)=1时,ap11(mod p),所以ap2a1(mod p),则ap2 mod m就是a的逆元。

模板

HDU1576,求A/B%MOD。

#include<cstdio>using namespace std;const int MOD=9973;int te,A,B;int exgcd(int a,int b,int &x,int &y){    if (!b) {x=1;y=0;return a;}    int r=exgcd(b,a%b,x,y),t=x;x=y;y=t-a/b*y;    return r;}int mul_INV(int a,int m){    int x,y;if (exgcd(a,m,x,y)!=1) return -1;    return (x%m+m)%m;}int main(){    freopen("mul_INV.in","r",stdin);    freopen("mul_INV.out","w",stdout);    scanf("%d",&te);    for (int i=1;i<=te;i++)    {        scanf("%d%d",&A,&B);        printf("%d\n",A*mul_INV(B,MOD)%MOD);    }    return 0;}
原创粉丝点击