三种求逆元总结(模板)

逆元定义:方程ax≡1(mod  p),的解称为a关于模p的逆,当gcd(a,p)==1(即a,p互质)时,方程有唯一解,否则无解。

一.扩展欧几里得求解

证明如下:

a*x + b*y = 1

如果ab互质,才有解

这个解的x就是a关于b的逆元

y就是b关于a的逆元

为什么呢?

两边同时求余b

a*x % b + b*y % b = 1 % b

a*x % b = 1 % b

a*x = 1 (mod b)

所以x是a关于b的逆元

反之可证明y

条件: a,p互质才能使用


#include<cstdio>
typedef long long LL;
void ex_gcd(LL a, LL b, LL &x, LL &y, LL &d){
    if (!b) {d = a, x = 1, y = 0;}
    else{
        ex_gcd(b, a % b, y, x, d);
        y -= x * (a / b);
    }
}
LL inv(LL t, LL p)
{//如果不存在,返回-1 
    LL d, x, y;
    ex_gcd(t, p, x, y, d);
    return d == 1 ? (x % p + p) % p : -1;
}
int main(){
    LL a, p;
    while(~scanf("%lld%lld", &a, &p)){
        printf("%lld\n", inv(a, p));
    }
}

二.费马小定律求逆元

证明如下:

费马小定律:假如p是质数,且gcd(a,p)=1,那么 a^(p-1)≡1(mod p)

由费马小定律我们可以想到是不是很像逆元的形式,即:

a*a^(p-2)≡1(mod p)

也就是说a^(p-2)是a的逆元。

条件:p是质数,且a不能被p整除!!(费马小定律成立条件),复杂度O(log2(p))

#include<bits/stdc++.h>
#define ll long long
using namespace std;
//前提条件 p是质数,a不能被p整除 
ll power_mod(ll a, ll b, ll mod)
{
    ll ans = 1;
    while (b)
    {
        if (b & 1) ans = ans * a % mod;
        a = a * a % mod;
        b >>= 1;
    }
    return ans;
}
int main(){
    ll a, p;
    while(~scanf("%lld%lld", &a, &p))
	{
		if(a%p==0) 
		printf("-1\n");
		else
        printf("%lld\n", power_mod(a,p-2,p));
    }
}

三.费马小定律扩展(用欧拉定律求逆元)

当p不是质数时就不能使用费马小定律了。

欧拉定律:若n,a为正整数,且n,a互质,则

其中φ(n)表示1~n中与n互质的数按顺序排布:x1,x2……xφ(n) (显然,共有φ(n)个数)

其实就是求出φ(p)后,与前面费马小定律的步骤一模一样。

条件:n,a为正整数,且n,a互质

四.用一般方法

注意这种方法不是用来求逆元的,而是用来化简(a/b)%p的

先介绍一下结论

证明

猜你喜欢

转载自blog.csdn.net/qq_39861441/article/details/89196402