zoukankan      html  css  js  c++  java
  • 浅谈扩展欧几里得定理(附裴蜀定理)

                                    关于扩展欧几里得定理

      众所周知,扩展欧几里得定理是用来求形如ax+by=c(a,b,c皆为整数)这样的方程的一组解[注,仅是一组解]的定理

      它的原理比较复杂,本人学了挺久才懂了一点,这里就不谈了,扩欧的核心是它的思想,它的思想可以用来解决许多题

     该方程有解的条件 :

       要使ax+by=c(a,b,c皆为整数) 有解,我们设k=gcd(a,b),可以将原方程写成frac{a}{k}kx+frac{b}{k}ky=c的形式

     即 k(frac{a}{k}x+frac{b}{k}y)=c

        ecause   a,b,c均为整数

     	herefore (frac{a}{k}x+frac{b}{k}y)一定是整数即k(frac{a}{k}x+frac{b}{k}y)一定是k的倍数

        	herefore   k|c 即 gcd(a,b)|c          //  k|c数学里为  c%k=0

        由此可见,该方程有解的条件为c%gcd(a,b)=0

      求解方法 :

        由于是求解ax+by=c的一组解,在方程有解的条件下,我们可以考虑先求出ax+by=gcd(a,b)的一组解,

        为什么这样考虑呢,这样子变化有什么好处呢?当我们将原方程转变为这样的方程之后,实际上我们求出的x与y并不是

        原方程的解,我们可以理解为转变后的方程的解为x'与y',实际上该ax+by=gcd(a,b)方程是将原方程除以

        c/gcd(a,b)后所得到的,所以原方程的解为left{egin{matrix} x=x'(c/gcd(a,b))& & \ y=y'(c/gcd(a,b))& & end{matrix}
ight.那么我们先求出ax+by=gcd(a,b)

        原方程的解便只需乘以c/gcd(a,b)就能得到了

        另外说明,c=gcd(a,b)是原方程有解的最小情况,利用这个性质,裴蜀定理也就不难写出来了

        那么该如何求解ax+by=gcd(a,b)呢?

        众所周知(又是这个词,词穷)   gcd的写法return b==0?a:gcd(b,a%b);(为了节约篇幅强行压缩)关键的一步就是

        gcd(a,b)==gcd(b,a%b)了,这个的成立性就不证明了,我们求解ax+by=gcd(a,b)是需要利用到gcd的这个特性的

        我们可以得到这样一个方程left{egin{matrix} & ax+by=gcd(a,b) & \ & gcd(a,b)=gcd(b,a mod b) & end{matrix}
ight.(这里的%显示不出来就用mod代替了),然后我们将gcd(b,a%b)中的b和a代入原方程

        那么可以得到gcd(b,a%b) = bx+(a%b)y,注意,此时的x与y也不是原方程的解,也可以理解为x',y'这样子我们就可以得到

        ax+by=gcd(a,b)=gcd(b,a mod b)=bx'+(amodb)y'(这里是将gcd(a,b)的a,b反代入原方程),又因为电脑中的取模运算a%b是等价于a-a/b*b的

        所以我们又可以将最后一个方程变成bx'+(a-a/b*b)y',然后与第一个方程放在一起便有

        dpi{150} ax+by=bx'+(a-a/b*b)y',然后拆项移项,变成ax+by=ay'+b(x'-a/by'),最后便能得出这样的转移方程

        left{egin{matrix} x=y' & \ y=x'-a/by' & end{matrix}
ight.,有了这样的转移方程,那么我们可以递归地写出代码了,递归结束条件就是b==0时,此时的方程

        ax+by=gcd(a,b),b==0,所以就是ax=a,那么x=1,y=0

       

    //已知a,b  求解  ax+by=1
    void ex_gcd (int a,int b,int &x,int &y)
    {
    	if (b==0){x=1,y=0;return;}
    	ex_gcd(b,a%b,x,y);
    	int tmp=x;
    	x=y,y=tmp-a/b*y;
    }
    /*
     * 若求解  ax+by=c
     * △条件(是否有解) : 满足gcd(a,b)|c [c%gcd(a,b)==0]
     * 可以先求  ax+by=gcd(a,b)
     * 再将求得的x与y分别乘以c/gcd(a,b)
     */

        那么扩展欧几里得便讲完了,下面说一下上文提到的裴蜀定理

        原题链接

      裴蜀定理

      题目描述

        给出n个数(A1...An)现求一组整数序列(X1...Xn)使得S=A1X1+...AnXn>0,且S的值最小

      输入输出格式

        输入格式:

        第一行给出数字N,代表有N个数 下面一行给出N个数

         输出格式:

        S的最小值

        我们可以将A1X1+A2X2+...+AnXn看成许多个ax+by,那么我们要求的便是c的最小值,上文说过,c的最小值就是gcd(a,b),所以我们只需求出所有的gcd便可

        附上代码

       

    #include <cstdio>
    #include <cmath>
    using namespace std;
    int ans,n,t;
    int gcd (int a,int b)
    {
    	return !b?a:gcd(b,a%b);
    }
    int main ()
    {
    	scanf("%d",&n);
    	scanf("%d",&ans);//ans初始赋值为第一个数
    	while (--n){
    		scanf("%d",&t);
    		t=abs(t);
    		ans=abs(gcd(ans,t));
    	}
    	printf("%d",ans);
    	return 0;
    }

        注,如若有误或者哪里讲得不清楚,请联系本人更改或者在下方留言,谢谢啦~(≧▽≦)/~

  • 相关阅读:
    C# Asp.net中简单操作MongoDB数据库(二)
    Windows下使用TeamViewer连接远程服务器,以及解决“远程桌面关闭后TeamViewer不能连接”的问题
    存储过程
    C# 使用MongoDB遇到的问题
    C# Asp.net中简单操作MongoDB数据库(一)
    Windows下MongoDB设置用户、密码
    退役狗也要搬博客
    codeforces840E In a Trap
    uoj207共价大爷游长沙
    bzoj2662: [BeiJing wc2012]冻结 最短路 建图
  • 原文地址:https://www.cnblogs.com/Morning-Glory/p/9784224.html
Copyright © 2011-2022 走看看