• 『笔记』扩展欧几里得(exgcd)


    定义

    扩展欧几里得算法是用来在已知一组 ((a,b)) 的时,求解一组 ((x,y)) 使得

    [ax+by=gcd(a,b) ]

    思想 and 板子

    根据相关的知识可以得到

    [gcd(a,b)=gcd(b,a mod b) ]

    由当 (b=0) 是即可得出 (x=1,y=0)

    即可递推求解

    如何来做?

    [ax+by=gcd(a,b)=gcd(b,a mod b) ]

    [bx+(a mod b)y=gcd(b,a mod b) ]

    [bx+(a-lfloorfrac{a}{b} floor imes b) imes y=gcd(b,amod b) ]

    [bx+ay-lfloorfrac{a}{b} floor imes by=gcd(b,amod b) ]

    [ay+b(x-lfloorfrac{a}{b} floor imes y)=gcd(b,amod b) ]

    进而可以得出结论

    [ax+by ]

    [ o ay+b(x-lfloorfrac{a}{b} floor imes y) ]

    有了结论就可以实现简单的求解

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

    为什么要用?

    在当前我的理解范围内,它既可以求出最大公约数,并且求出来的 (x,y) 可以进行解决一些问题

    应用

    可用于进行对二元一次不定方程的求解

    [ax+by=c ]

    根据裴蜀定理可得,这个方程有整数解的充要条件为

    [c mod gcd(a,b)=0 ]

    同样,该方程可以等同于

    [ax equiv c (mod b) ]

    P5656 板子可以为较为拓展的应用

    1、如何来求 (ax+by=c) 的一个解

    首先我们在有整数解的情况下求出

    [ax+by=gcd(a,b) ]

    的解 ((x_0,y_0))

    (k=frac{c}{gcd(a,b)})

    得出来

    该方程的一个解可以为

    (egin{cases} x=kx_0\y=ky_0 end{cases})

    也就是方程在同除完 (k) 后求出解来,进而乘上 (k) 得出当前的解,因为(a,b)是不变的

    2、如何根据一组解求出多组解来

    首先任意选择一个数(t),为了方便叙述和计算,一般设(t=1)

    设两个整数 (m,n)

    我们可以得出

    [a(x+m)+b(y+n)=c ]

    [ax+am+by+bn=c ]

    [ax+by=c ]

    可知

    [am+bn=0 ]

    那么就是寻找一组 ((m,n))使得该方程 成立即可

    可以得到

    (egin{cases} m=frac{b}{gcd(a,b)}\n=-frac{a}{gcd(a,b)} end{cases})

    代进去等式成立,进而就可以得到一组解

    (egin{cases} x_i=x+m\y_i=y+n end{cases})

    3、考虑正整数解的最大值最小值,及其正整数解的个数

    首先设置一下变量

    (egin{cases} d=gcd(a,b)\tx=frac{b}{d} \ty=frac{a}{d} end{cases})

    首先那我们从x的最小值开始找起

    可以得到式子

    [x+k imes txge 1 ]

    [kge lceilfrac{1-x}{tx} ceil ]

    得到(x_{min}=x+lceilfrac{1-x}{tx} ceil imes tx)

    那么此时同样可以得到 (y_{max}=y-lceilfrac{1-x}{tx} ceil imes ty)

    • 如果此时没有(y_{max})不是正整数的话

    那么就在求一下

    [y_{max}+k imes tyge1 ]

    [kge lceilfrac{1-y_{max}}{ty} ceil ]

    那么 (y) 的最小正整数解即为 (y_{max}+lceilfrac{1-y_{max}}{ty} ceil imes ty)

    同样适用于有正整数解情况下的(y_{min})

    • 如果此时有正整数解

    可以很显然的发现(y_{min}=y_{max}mod ty)

    利用情况一中的结论可以求出

    [x_{max}=x_{min}-lceilfrac{1-y_{max}}{ty} ceil imes tx ]

    至于解的个数可以参考在(y_{max} o y_{min})过程中 $ k $的变化

    正整数解的组数即为 (lfloorfrac{y_{max}-1}{ty} floor+1)

    代码请参考P5656

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<stack>
    #define int long long
    using namespace std;
    int x,y;//用于求解 
    int read()//不到卡常不用快读=_= 
    {
    	char c=getchar();
    	int f=1;
    	int x=0;
    	while(c<'0'||c>'9')
    	{
    		if(c=='-')
    			f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9')
    	{
    		x=(x<<1)+(x<<3)+(c^'0');
    		c=getchar();
    	}
    	return x*f;
    }
    int exgcd(int a,int b)
    {
    	if(!b)
    	{
    		x=1;
    		y=0;
    		return a;
    	}
    	int ans=exgcd(b,a%b);
    	int tmp=x;
    	x=y;
    	y=tmp-a/b*y;
    	return ans;
    }
    signed main()
    {
    	int t;
    	t=read();
    	while(t--)
    	{
    		int a,b,c;
    		a=read();
    		b=read();
    		c=read();
    		int d=exgcd(a,b);
    		if(c%d!=0)//根据裴蜀定理得出,c不是gcd(a,b)的倍数,则一定无整数解 
    		{
    			cout<<-1<<endl;
    			continue;
    		}
    		x=x*c/d;
    		y=y*c/d;//求出一组正整数解
    		int tx=b/d;
    		int ty=a/d;
    		int k=ceil((1.0-x)/tx);//求出x_min正整数;判断y是否为正整数 
    		x+=k*tx;//x_min
    		y-=k*ty;//求出此时的ymax 
    		if(y<=0)
    		{
    			int ymin=y+ty*ceil((1.0-y)/ty)*1ll;
    			printf("%lld %lld
    ",x,ymin); 
    		}
    		else 
    		{
    			printf("%lld ",(y-1)/ty+1);//个数 
    			printf("%lld ",x);//最小值 
    			printf("%lld ",(y-1)%ty+1);//最小值 
    			printf("%lld ",x+((y-1)/ty*tx));//max 
    			printf("%lld 
    ",y);//max
    		}
    		continue;
    	} 
    	return 0;
    } 
    
  • 相关阅读:
    HTML DOM教程 14HTML DOM Document 对象
    HTML DOM教程 19HTML DOM Button 对象
    HTML DOM教程 22HTML DOM Form 对象
    HTML DOM教程 16HTML DOM Area 对象
    ubuntu 11.04 问题 小结
    VC6.0的 错误解决办法 小结
    boot.img的解包与打包
    shell里 截取字符串
    从零 使用vc
    Imagemagick 对图片 大小 和 格式的 调整
  • 原文地址:https://www.cnblogs.com/1123LXY/p/14249741.html
Copyright © 2020-2023  润新知