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

扩展欧几里得算法:

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

设:设:

r0=q1∗r1+r2r_{0}=q_{1}*r_{1}+r_{2}r0=q1r1+r2

r1=q2∗r2+r3r_{1}=q_{2}*r_{2}+r_{3}r1=q2r2+r3

r2=q3∗r3+r4​r_{2}=q_{3}*r_{3}+r_{4}​r2=q3r3+r4

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

rk−1=qk∗rk​r_{k-1}=q_{k}*r_{k}​rk1=qkrk

其中rk​r_{k}​rk 就是最大公约数,因为rk​r_{k}​rk可由rk−1​r_{k-1}​rk1rk−2​r_{k-2}​rk2,且rn=rn−2−qn−1∗rn−1​r_{n}=r_{n-2}-q_{n-1}*r_{n-1}​rn=rn2qn1rn1

rk−1​r_{k-1}​rk1可表示为rk−2​r_{k-2}​rk2rk−3​r_{k-3}​rk3的线性组合

同理rk−2r_{k-2}rk2也可向上表示。这样得到最大公约数之后,一直向上回溯即可找到满足条件的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;
}

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

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

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

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

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

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

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

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

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

即:a​a​a 关于p​p​p 的逆元为 ap−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;
}

转载于:https://www.cnblogs.com/dchnzlh/p/10427225.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值