扩展欧几里得算法:

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

设:

a为r0,b为r1

r 0 = q 1 r 1 + r 2 r_{0}=q_{1}*r_{1}+r_{2} r0=q1r1+r2

r 1 = q 2 r 2 + r 3 r_{1}=q_{2}*r_{2}+r_{3} r1=q2r2+r3

r 2 = q 3 r 3 + r 4 r_{2}=q_{3}*r_{3}+r_{4}​ r2=q3r3+r4

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

r k 1 = q k r k r_{k-1}=q_{k}*r_{k}​ rk1=qkrk

其中 r k r_{k}​ rk 就是最大公约数,现在我们可以得到 0 r k 1 + r k = g c d 0*r_{k-1}+r_{k}​=gcd 0rk1+rk=gcd.
又因为 r k r_{k}​ rk可以写成 r k 1 r_{k-1} rk1 r k 2 r_{k-2} rk2的代表公式即 r k = r k 2 q k 1 r k 1 r_{k}​=r_{k-2}-q_{k-1}*r_{k-1} rk=rk2qk1rk1,所以我们又能得到 x r k 2 + r k 1 = g c d x*r_{k-2}+r_{k-1}=gcd xrk2+rk1=gcd的 x 和 y 了

同理 r k 3 r k 2 r_{k-3}和r_{k-2} rk3rk2也可向上表示。一直向上回溯即可找到满足条件 x a + y b = g c d x*a+y*b=gcd xa+yb=gcd x x x y y 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;
}

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

gcd(a,m) | c ,即gcd(a,m) 是c的因子

形如式子 a x = c <mtext>     </mtext> ( m o d <mtext>    </mtext> m ) a*x=c\ \ \ (mod \ \ m) ax=c   (mod  m),求满足条件的x。

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

a x 1 + m y 1 = g c d ( a , m ) <mtext>         </mtext> ax_{1}+my_{1}=gcd(a,m)\ \ \ \ \ \ \ ① ax1+my1=gcd(a,m)       

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

那么等式①两边同乘以 c 1 c_{1}​ c1即可得到 a x 1 c 1 + m y 1 c 1 = c ax_{1}c_{1}+my_{1}*{c1}=c​ ax1c1+my1c1=c

x = x 1 c 1 = x 1 c / g c d ( a , m ) x=x_{1}*c_{1}=x_{1}*c/gcd(a,m)​ x=x1c1=x1c/gcd(a,m) x 1 x_{1}​ x1 ( a , m ) (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 ( m o d <mtext>   </mtext> p ) a^{φ(p)}=1(mod \ p)​ aφ(p)=1(mod p)

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

则: a p 1 = 1 <mtext>   </mtext> ( m o d <mtext>   </mtext> q ) a^{p-1}=1\ (mod \ q)​ ap1=1 (mod q)

即: a a​ a 关于 p p​ p 的逆元为 a p 2 a^{p-2}​ ap2

/* 快速幂取模即可 */

利用扩展欧几里得求逆元

前提

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;
}