• 『笔记』扩展欧几里得(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;
    } 
    
  • 相关阅读:
    Spring MVC+FreeMarker简介
    集合框架
    异常处理
    c语言中的一些注意点
    在ScrollView中自定义GridView无法显示全部的问题的解决
    Android 发送request请求在服务器端解析时乱码
    Android 4.1 APP中的static变量即使在APP退出后仍然不会被擦除
    关于Android的asynctask-threads-limits问题:asynctask开启的线程是否有极限
    ListView中各组件点击事件冲突,ListView不响应OnItemClickListener事件
    异常:java.lang.NoClassDefFoundError: com.android.volley.toolbox.Volley
  • 原文地址:https://www.cnblogs.com/1123LXY/p/14249741.html
Copyright © 2020-2023  润新知