exGCD 2025/1/10
前言:
    全文均为蒟蒻作者手搓
    虽也参考了许多 [luogu 题解/某SDN/cnblogs.com]
    但很多地方均为作者瞎编
    如有错误务必救救孩子
File
int GCD(int a,int b){
	if(b==0)return a;
	return GCD(b,a%b);
}


Question 01 [贝祖定理]
根据 ax+by=GCD(a,b)
a,b均为正整数
求x,y的整数值。

Solution
因为ax+by=GCD(a,b)
并且GCD(a,b)=GCD(b,a%b)
所以ax+by=GCD(b,a%b)
由贝祖定理GCD(b,a%b)=bX+a%bY
我们求出x,y和下一层X,Y的关系扔到递归里求解即可
等量代换ax+by=bX+a%bY
又因为a%b=a-(a/b)*b (C++向下取整)
所以
ax+by=bX+[a-(a/b)*b]Y
	 =bX+aY-b*(a/b)*Y
	 =aY+b[X-(a/b)*Y]
所以得到
x=Y
y=X-(a/b)*Y
但是递归需要出口
当b=0GCD(a,b)=a
即当b等于0,ax+by=a
把b代入 ax+0y=a
显然此时x=1
y可以取任意整数
However
你能见到的 STD 都会把 y=0
为什么呢
因为 y= Rand()
不一定能满足上一层
GCD(a,b)=GCD(b,a%b)=b
而此时 a%b=0
代一下贝祖
ax+by=b
代入上一层
aY+b(X-a/b*Y)=b
显然 X=1,Y=0 仍然可以
但是 Y!=0 就不一定了
因为作者懒就统一写成 x=1,y=0 了
Code
//求解
//exGCD 函数的返回值是GCD(a,b)
//x,y 用引用的方式取回x,y的结果
int exGCD(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	//刚才得到的式子
	int X,Y;
	int GCD_answer=exGCD(b,a%b,X,Y);
	x=Y;
	y=X-(a/b)*Y;
	return GCD_answer;
}

当然,该式子不是常见形式
我们可以直接把形参中的x,y传进去
用y记录Answer中“X”的值,x记录“Y”的值
此时
x=Y(correct)
y=X
显然y应该-=(a/b)*Y
而Y的值被x所记录
所以 y-=(a/b)*x

Code Improved
int exGCD(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int GCD_answer=exGCD(b,a%b,y,x);
	y-=(a/b)*x;
	return GCD_answer;
}


Question 02 [线性同余方程]
根据 ax%m=b
a,b,m均为正整数
求 x
无解输出“Shit!”

Solution
因为 ax%m=b
其等价于 ax=b+km
所以 ax-mk=b
定义 y=-k
所以 ax+my=b
而 Question 01 则是根据 ax+by=GCD(a,b) 求x,y的整数值。
这就要求 b=GCD(a,m)
但是显然有时b不等于GCD(a,b)却仍然有解

example a=3 m=5 b=3
GCD(a,m)=1
但 x=6 是不定方程的解

注意到若 b%GCD(a,b)==0
则 b=B*GCD(a,b) B为整数
ax+my=b 变为 ax+my=B*GCD(a,b)
已知求法的是 aX+mY=GCD(a,b)
显然
x=B*X
y=B*Y
是原方程的一组解

Code

#include<bits/stdc++.h>
using namespace std;
int exGCD(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int GCD_answer=exGCD(b,a%b,y,x);
	y-=(a/b)*x;
	return GCD_answer;
}
int main(){
	int T,a,b,m,x,y,gcd_ans;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&a,&b,&m);
		gcd_ans=exGCD(a,m,x,y);
		if(b%gcd_ans==0){
			printf("%d\n",(long long)x*b/gcd_ans%m);
		}else{
			puts("Shit!");
		}
	}
}

Question 03 [逆元]
根据 ax%m=1x (a 关于 m 的逆元)
要求 0<x<m
如没有输出“impossible”

Solution
此题为 Question 02 弱化版
ax+my=1
要求 1%GCD(a,m)=0GCD(a,m)=1
即   a,m 互质

Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
int exGCD(int a,int b,int &x,int &y){
	if(b==0){
		x=1,y=0;
		return a;
	}
	int GCD_answer=exGCD(b,a%b,y,x);
	y-=(a/b)*x;
	return GCD_answer;
}
signed main(){
	int T,a,m,x,y;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d",&a,&m);
		if(exGCD(a,m,x,y)==1){
			printf("%d\n",(x%m+m)%m);
		}else{
			puts("impossible");
		}
	}
}

Question 04 [P5656 exGCD]
给定不定方程 ax+by=c
1. 若该方程无整数解
   输出 -1
2. 若该方程有整数解且有正整数解
   输出其正整数解数量、所有正整数解中 x 的最小值、y 的最小值、x 的最大值、y 的最大值
3. 若方程有整数解但没有正整数解
   输出所有整数解中 x 的最小正整数值、 y 的最小正整数值

Answer
Question 01 主体 + Question 02 思路
我们已经会求 ax+by=GCD(a,b)
根据 Question 02 可知
只要 c|GCD(a,b) 即可
否则无解
第一条解决

现在假设我们已经求出一组解 x,y 使 ax+by=GCD(a,b)
目标是求出所有解 X,Y ,使 aX+bY=c //注意这里!
我们简写 GCD(a,b) 为 gcd,设c=base*gcd
ax+by=gcd
a*(x*base)+b*(y*base)=c
得到
{X=x*base
{Y=y*base
为原方程的一组解

接下来我们从一组解推所有的解
设 a(X+m)+b(Y+n)=c
展开得 (aX+bY)+(am+bn)=c
代入 c+(am+bn)=c
所以 am+bn=0

简单思考可能会得到
{m=kb
{n=-ka
但其实它不对(会有遗漏)
我们就想凑出一个数使其有 a,b 两个约数
而最小的,...
应该是LCM(a,b)//不是LCA啊喂
众所周知
LCM(a,b)=a*b/GCD(a,b)
所以
m 和 n 应都除上 gcd

fixed
{m=kb/gcd
{n=-ka/gcd

所以使劲带入一下
{X=x*base+kb/gcd
{Y=y*base-ka/gcd
(k 是正整数)
可以看出当 k 增大的时候 X 越来越大 Y 越来越小

接下来我们试着求一下 X(min)//正整数解
由题需要 k 尽量小
因为要求其是正整数
所以 x*base+kb/gcd>=1
所以 kb/gcd>=1-x*base
所以
	 1-x*base
k>= ----------- (double)
	   b/gcd

but!
double 显然不甚理想
所以将其上取整
example
k>=4.5
k 必然是 5 而非 4

所以
X(min)=x*base+(1-x*base+b/gcd-1)/(b/gcd)*b/gcd//上取整 so 别化简了
	  =x*base+(b/gcd-x*base)/(b/gcd)*b/gcd
 //这个结果是作者自己推导的
 //有问题欢迎指出
 //一定诚挚感谢并%神犇好人
根据奇妙的原理
此时 Y 取 max
aX(min)+bY(max)=c
Y(max)=(c-aX(min))/b

此时如果 Y(max)<0 那么没有正整数解

求个 Y(min)
需要 k 尽量大
y*base-kb/gcd>=1
所以 -kb/gcd>=1-y*base
所以
	 y*base-1
k<= -----------
	   b/gcd
这个就是下取整了
Y(min)=y*base+(y*base-1)/(b/gcd)*b/gcd
X(max)=(c-b*Y(min))/a;

luogu 网友温馨提示我:
    十年 OI 一场空,不开 long long 见祖宗!
    孩子...虽然我不在了...但你要拾起我的旗帜...并打开快读...
    
So...QED...了吗

Code


后记:
写到此处我很想写一些文采斐然的语句表示我强烈的情感
但想到管理还要看
唉...
还是算了
posted on   2025ing  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 本地部署 DeepSeek:小白也能轻松搞定!
· 如何给本地部署的DeepSeek投喂数据,让他更懂你
· 从 Windows Forms 到微服务的经验教训
· 李飞飞的50美金比肩DeepSeek把CEO忽悠瘸了,倒霉的却是程序员
· 超详细,DeepSeek 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方Dee
点击右上角即可分享
微信分享提示