• 扩展欧几里得算法(exgcd)


    前言

    1

    (gcd(a,b)=gcd(b,a\%b),(gcd(a,0)=a))

    小证一下吧

    (d=gcd(a,b))(a=d*k,b=d*k')

    (a\%b!=0),则 (a\%b=a-leftlfloor dfrac ab ight floor * b = (k-leftlfloor dfrac ab ight floor*k')d) 并没有损失掉 (d)

    (a\%b=0) 时,(b=gcd(a,b))

    2

    (a*x+b*y=c) 有解当且仅当 (gcd(a,b)|c)

    这个就不多说了

    exgcd

    扩展欧几里得算法,求解出一组解 (x,y) 使得 (a*x+b*y=gcd(a,b))

    我们当前有 (gcd(a,b)=gcd(b,a\%b),a\%b=a-leftlfloor dfrac ab ight floor * b)

    (b) 代替 (a) , 用 (a\%b=a-leftlfloor dfrac ab ight floor * b) 代替 (b) 则原式成为

    (b*x'+(a-leftlfloor dfrac ab ight floor * b)*y'=gcd(a,b)) 注意 (x' e x,y' e y)

    我们大力化式子,差开 ((a-leftlfloor dfrac ab ight floor * b)*y)

    原式变为

    (b*x'+a*y'-b*leftlfloor dfrac ab ight floor*y'=gcd(a,b))

    (a)(b) 放到一起

    (a*y'+b*(x'-leftlfloor dfrac ab ight floor*y')=gcd(a,b))

    因此我们得出 , (x=y',y=x'-leftlfloor dfrac ab ight floor*y')

    当我们求出 (gcd(a,b))(b=0) 此时 (a*x+b*y=a) 我们让 (x=1,y=0) 即可

    这样反向推回去就行了

    放下代码吧

    int exgcd(int a,int b,int &x,int &y){
    	if(!b){ x=1,y=0; return a; }
    	int gcd=exgcd(b,a%b,y,x);
    	y-=a/b*x;
    	return gcd;
    }
    

    最后我们求得了 (a*x+b*y=gcd(a,b)) 如何求 (a*x+b*y=c) 呢?

    (x,y) 分别乘上 (dfrac c{gcd(a,b)}) 就行了


    现在我们已经求出了一组解 (x,y)如何得到另一组解 (x',y') 呢?

    只需要让 (x'=x+dfrac{b}{gcd(a,b)},y'=y-dfrac{a}{gcd(a,b)}) 即可

    证明

    (x',y') 带入 (a*x+b*y=gcd(a,b)) 中 发现多出来的项消掉了

    简单推导可知,这是 (x,y) 所能变动的最小范围


    那么,我们知道了这个,就可以求出 (x) 的最小整数解,只需要让 (x\%dfrac b{gcd(a,b)}) 就行了

    写公式好累啊,啊啊啊,就当复习了

  • 相关阅读:
    tfidf 问题
    Win32汇编窗口程序设计[03]第一个窗口程序
    Win32汇编窗口程序设计[01]开发环境的搭建
    Win32汇编窗口程序设计[02]RadASM简介
    寄存器引用结构体变量
    始终居中的弹出层
    JSonJavaScript
    json
    <收录>jqueryuidatapicker生成的页面html
    网站数据抓取
  • 原文地址:https://www.cnblogs.com/XiaoVsun/p/13054280.html
Copyright © 2020-2023  润新知