逆元的求法

预防针:本文排版很乱,介绍概念时并不专业(不过能用就好了)

这里有专业的讲解,但是我不怎么看的懂就是了:https://blog.csdn.net/xiaoming_p/article/details/79644386

Part I 概念介绍:

我们想要(A/B)%P,其中A,B代表一个式子,因此可能本身A,B就超过自己的数据范围,都爆了,还怎么除呢?

我们能想到的是(A%P)/(B%P)%P  (A%P具体举栗子就是A = a*b,然后(a%P)*(b%P)%P)

不过这样算出来的答案是错误的,很明显啦,因为是除法呀。(总的来说我讲不清

所以我们用乘法做,乘法各自取模再相乘是不会出错的。

(A%P)*((1/B)%P)%P

但是很明显1/B是个小数啊。。。

所以我们要找一个数X,使得A*X%P = (A/B)%P

X就是B 在 模 P 下的逆元

Part II:逆元的求法

① 利用一个结论:(适用于P是质数)

当P为质数时:X^P %P = X%P

我们左右各除X^2,得到:X^(P-2) %P =(1/X)%P

因此,结论为:求B在P下的逆元,只要P是质数,B的逆元 = B^(P-2)

因为P可能很大,所以用快速幂。

代码:

#include
#include
#define ll long long
#define mod (ll)1000000007

using namespace std;

ll fast_power(ll a,ll b)
{
    ll ans = 1;
    while (b){
        if (b&1) ans = (ans*a)%mod;
        b >>=1;
        a = (a*a)%mod;
    }
    return ans;
}

int main()
{
    ll a;
    printf("输入一个数求它在模1e9+7下的逆元\n");
    scanf("%lld",&a);
    ll ans = fast_power(a,mod-2);
    printf("%lld%在 1e9+7 下的逆元=%lld\n",a,ans);
    return 0;
}

②利用exgcd(扩展欧几里得算法)求解二元一次方程(P是不是质数都可以)

关于exgcd可以参考这篇:https://blog.csdn.net/weixin_43768644/article/details/94771375

又有一个结论:

A在模P下的逆元X,满足  A*X%P = 1%P   (已知X%P = (1/A)%P对吧,两边乘A就可以了)

这个式子可以理解为 A*X = 1+k*P,就是A*逆元 = 整数倍的P+1

A,P已知,那么就变成了二元一次方程:A*X-k*P = 1       的求解问题,用exgcd即可

然后:一定要扔P,不要扔-P到exgcd。

扔-P你求的是

A*x - P*y = (gcd(A,-P)=-1)的解 

扔P求的是

A*x + P*(-y)=(gcd(A,P)=1)       ///虽然y反了,但是x没有问题

根据exgcd存在解的先决条件来看(上面那篇里面有讲到),(A/B)%P,B存在逆元的条件是A,B互质,因为exgcd只能求

ax+by=gcd(a,b)的解,如果a,b互质,那么gcd(a,b)>1,原式无解

代码:

#include
#include
#define ll long long
#define mod (ll)1000000007

using namespace std;

void exgcd(ll a,ll b,ll& x,ll& y)
{
    if (b==0){x = 1;y = 0;}
    else {
        exgcd(b,a%b,y,x);
        y = y - (a/b)*x;
    }
}

int main()
{
    ll a;
    printf("输入一个数,求它在1e9+7下的逆元\n");
    scanf("%lld",&a);
    ll x,y;
    exgcd(a,mod,x,y);///bx + p(-y) = 1
    x = (x+mod)%mod;
    printf("%lld%在 1e9+7 下的逆元=%lld\n",a,x);
    return 0;
}

 

 

 

 

 

 

你可能感兴趣的:(数论)