扩展欧几里得算法 以及求逆元的几种方法

扩展欧几里得算法:

ax+by=gcd(a,b)ax+by=gcd(a,b)​ 求出满足条件唯一的x,y的值

设:

r0=q1r1+r2r_{0}=q_{1}*r_{1}+r_{2}

r1=q2r2+r3r_{1}=q_{2}*r_{2}+r_{3}

r2=q3r3+r4r_{2}=q_{3}*r_{3}+r_{4}​

....................

rk1=qkrkr_{k-1}=q_{k}*r_{k}​

其中rkr_{k}​ 就是最大公约数,因为rkr_{k}​可由rk1r_{k-1}​rk2r_{k-2}​,且rn=rn2qn1rn1r_{n}=r_{n-2}-q_{n-1}*r_{n-1}​

rk1r_{k-1}​可表示为rk2r_{k-2}​rk3r_{k-3}​的线性组合

同理rk2r_{k-2}也可向上表示。这样得到最大公约数之后,一直向上回溯即可找到满足条件的x,y

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    ll gcd=ExGcd(b,a%b,x,y);
    ll temp,k;
    k=a/b;
    temp=x;
    x=y;
    y=temp-k*y;
    return gcd;
}

利用扩展欧几里得求一次同余方程

形如式子ax=c   (mod  m)a*x=c\ \ \ (mod \ \ m),求满足条件的x。

  • 且只有满足gcd(a,m)cgcd(a,m)|c 的时候才有解。

ax1+my1=gcd(a,m)       ax_{1}+my_{1}=gcd(a,m)\ \ \ \ \ \ \ ①

c1=c/gcd(a,m)c_{1}=c/gcd(a,m),

那么等式①两边同乘以c1c_{1}​即可得到ax1c1+my1c1=cax_{1}c_{1}+my_{1}*{c1}=c​

x=x1c1=x1c/gcd(a,m)x=x_{1}*c_{1}=x_{1}*c/gcd(a,m)​x1x_{1}​(a,m)(a,m)​的扩展欧几里得公式中a的系数)

#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    ll gcd=ExGcd(b,a%b,x,y);
    ll temp,k=a/b;
    temp=x;
    x=y;
    y=temp-k*y;
    return gcd;
}
bool IsOk;
ll calc(ll a,ll c,ll m)
{
    ll x,y;
    ll gcd=ExGcd(a,m,x,y);
    if(c%gcd!=0)
    {
        IsOk=false;
        return 0ll;
    }
    return c/gcd*x%m;
}

利用费马小定理求逆元

补充一个 欧拉定理:

设φ(x)的x的欧拉函数值,如果有a和p互素,则有

aφ(p)=1(mod p)a^{φ(p)}=1(mod \ p)​

  • 费马小定理条件:a,p互素,且p是素数

则:ap1=1 (mod q)a^{p-1}=1\ (mod \ q)​

即:aa​ 关于pp​ 的逆元为 ap2a^{p-2}​

/*
快速幂取模即可
*/

利用扩展欧几里得求逆元

前提

gcd(a,q)==1

逆元即ax+qy=1 (mod q)中的x

#include<cstdio>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn=1e4+10;
ll ExGcd(ll a,ll b,ll &x,ll &y)//求 a b 最大公约数,且得到gcd(a,b)=x*a+y*b;
{
    if(!b)
    {
        x=1;
        y=0;
        return a;
    }
    ll gcd=ExGcd(b,a%b,x,y);
    ll temp,k;
    k=a/b;
    temp=x;
    x=y;
    y=temp-k*y;
    return gcd;
}
ll getinv(ll a,ll m)
{
    ll x,y;
    if(ExGcd(a,m,x,y)!=1)
        return -1;//不互质 不存在逆元
    return x;
}

posted @ 2019-01-31 23:35  _年少有为  阅读(5331)  评论(0编辑  收藏  举报