gcd与exgcd

gcd——最大公约数
基本求法为辗转相除(欧几里得算法),有一些优化,网上搜得到就不详细说明了。
辗转相除(x>=y):gcd(x,y)=gcd(y,x%y) 当y=0时,答案为x
代码如下:

inline int gcd(int x,int y)
{
    return y?gcd(y,x%y):x;
}

代码极其简短….
下面是exgcd(扩展欧几里得算法),用来装逼处理ax+by=c=gcd(a,b)*k的同余方程
易证 当c%gcd(a,b)不等于0时,该方程无整数解。反之,则有无数整数解
扩欧的思想就是把欧几里得算法在方程中不断转换,并利用恒等定律,递归求出x,y的一组解
下面是一步递归的演算过程:

①ax1+by1=gcd(a,b)
②bx2+(a%b)y2=gcd(b,a%b)
∴ax1+by1=bx2+(a%b)y2
ax1+by1=bx2+(a-(a/b)」*b)y2;
ax1+by1=bx2-b*(a/b)」y2+ay2
ax1+by1=ay2+b(x2-y2*(a/b)」)

∴x1=y2,y1=x2-y2*(a/b)」
那么这个过程就可以在gcd过程中完成,在gcd的过程中完成对x和y的赋值
结果在什么地方呢?
那么根据gcd函数的结果,最后b一定会等于0。
当b=0时,gcd(a,0)=a原方程也就变成了ax=a 显然。。。此时x=1。
那么久可以回溯了
代码也是极其短小精悍(我才没压行

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

下面附vijos1009 exgcd的程序 可以参考 爱抄不抄

#include<iostream>
#include<cstring>
#include<cstdio>
#define LL long long
using namespace std;
LL x,y,m,n,L,a,b,c;

inline LL gcd(LL a,LL b){
    if (!b) return a;
    else return gcd(b,a%b);
}

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

int main(){
    scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&L);

    a=n-m; b=L; c=x-y;
    if(a<0)
    {
        a=-a;c=-c;
    }
    LL t=gcd(a,b);
    if (c%t){
        printf("Impossible\n");
        return 0;
    }
    a/=t; b/=t; c/=t;
    x=y=0;
    exgcd(a,b,x,y);
    x=((c*x)%b+b)%b;
    if (!x) x+=b;
    printf("%lld\n",x);
}

补:exgcd求逆元
今天上课突然讲到逆元。。想起来这里还有个坑没填- -
a*b≡1(mod p)则称a,b在p的模域下互为逆元
当p=∞,a=1/b
但是如果p是有限的,那么就不是那么简单了
欧拉函数求逆元和。。a^p-2次方我这里就不说了,毕竟主题是exgcd

上面讲过exgcd求的是:“Ax+By=gcd(A,B)”这样一个式子,然而显然只有在上述的a和p互质的情况下才存在逆元
所以gcd(a,b)=1,很容易理解
a*b≡1(mod p),我们可以转化为a*b-p*L=1
即a*b+p*(-L)=1
那么另b=x,p=B,a=A,(-L)=y;
则原式=A*x+B*y=1=gcd(A,B)
那么这个式子就可以用exgcd求解了
exgcd(a,p,x,y)
得到的x,即为a在p模域下的乘法逆元
——end

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值