• 扩展欧几里得算法详解


    本篇将附上扩展欧几里得算法的思想与推导;


    对于一个方程(a*x+b*y=gcd(a,b))来说,我们可以做如下的推导:

    设有(a*x_1+b*y_1=gcd(a,b));

    同时我们有(b*x_2+(a\%b)*y_2=gcd(b,a\%b));

    对于这个方程组,我们希望知道的是(x_1,x_2,y_1,y_2)之间的关系,这样我们才可以递归解决这个问题

    我们观察(b*x_2+(a\%b)*y_2)这个式子,我们可以将((a\%b))写作((a-lfloorfrac{a}{b} floor*b)),将括号打开常数(a,b)合并,合并之后的结果为(a*y_2+b*(x_2-lfloorfrac{a}{b} floor*y_2)))

    由于欧几里得算法的原理(gcd(a,b)==gcd(b,a\%b)),我们将两式子联立,对比系数即可得到(x_1=y_2,y_1=x_2-lfloorfrac{a}{b} floor*y_2)

    这个递归的边界是什么呢?我们知道,当朴素欧几里得到达边界时,(return gcd(a,0)=a),那么边界条件就是对(a*x_0+b*y_0=a)求解,很显然,此时(x_0=1,y_0=0)

    当我们递归求出了一个方程的特解时,如何求出这个方程的通解呢?

    方程(a*x+b*y=gcd(a,b))中,如果将x加上一个常数(k_1,y)减去一个常数(k_2),仍然保持原方程成立,那么(x+k_1,y-k_2)就是方程的一个新解,这个k应该如何选择呢?

    实际上很简单,(a*(x+k_1)+b*(y+k_2)=gcd(a,b)),打开括号,(a*x+a*k_1+b*y-b*k_2=gcd(a,b));

    我们保证原方程成立,就需要(a*k_1==b*k_2),那么显然(k_1=b,k_2=a)是一种合理的情况,但是这样是无法包含所有整数解的,因为我们加上的这个值并非是最小值

    那我们应该加上什么值才行呢?我们发现当(a*k_1==b*k_2=t*lcm(a,b))可以保证得到所有解,于是每次寻找解就可以分别在(x)加上(frac{b}{gcd(a,b)},在y减去frac{a}{gcd(a,b)})就可以了

    对于方程(a*x+b*y=c)我们又该如何求解?我们发现如果((c\%gcd(a,b)!=0))那么这个方程是无解的,而如果(gcd(a,b)*t==c),我们就可以按上面的方法求解之后对我们的解乘上一个(t(t=frac{c}{gcd(a,b)}))

    (code:)

    
    int exgcd(int a,int b,int &x1,int &y1)
    {
    	if(!b)
    	{
    		x1=1,y1=0;
    		return a;
    	}
    	int x2,y2;
    	int d=exgcd(b,a%b,x2,y2);
    	x1=y2,y1=x2-(a/b)*y2;
    	return d;
    }
    
  • 相关阅读:
    单片机触摸屏校准
    C中的预编译宏定义
    Android之网络摄像头
    曾经的UCOSii
    关于ST-Link下载STM32程序的使用
    关于IAR开发STM32配置
    学习C#(一)
    ESP8266使用详解--基于Lua脚本语言
    (五)Lua脚本语言入门
    (四)Lua脚本语言入门(数组遍历)
  • 原文地址:https://www.cnblogs.com/KatouKatou/p/9818175.html
Copyright © 2020-2023  润新知