Luogu P1082 同餘方程

Luogu P1082 同餘方程


擴展歐幾里得

本題良心題解

code:

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
#define ll long long

ll a,b,x,y;

void exgcd(ll aa,ll bb)
{
	if(bb==0)
	{
		x=1;
		y=0;
		return ;
	}
	exgcd(bb,aa%bb);
	ll t1=x;
	x=y;
	y=t1-(aa/bb)*y;
}

int main()
{
	scanf("%lld %lld",&a,&b);
	exgcd(a,b);
	printf("%lld",(x%b+b)%b);
}

來源:https://www.luogu.org/blog/cicos/solution-p1082
圖片來源:https://www.luogu.org/blog/cicos/solution-p1082


擴歐複述:

裴蜀定理:
存在x,y使得a,b滿足ax+by=m.
a,b,x,y都是整數,且m一定是gcd(a,b)的倍數

普通的gcd:
求aa和bb的最大公約數
int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}

當找到最後,b==0時,a就是最大公約數了,我們叫此時的b爲b1,a爲a1
滿足 a1 * x1+b1 * y1=gcd(a1,b1)=gcd(aa,bb)=a,
顯然此時x1=1,y1=0

但是a1不是aa,b1也不是bb
那如果要求aa * xx+bb * yy=m呢
先求aa * xx+bb * yy=gcd(aa,bb)吧
我們可以從現在的a1,b1,遞歸回aa,bb

假設當前我們在求a2和b2的最大公約數,
而我們已經求出了下一個狀態:b2和a2%b2的最大公因數,
並且求出了一組x2和y2使得
b2 * x2+(a2 % b2) * y2=gcd
把a2 % b2=a2-a2 / b2 * b2(這個除向下取整哈) 代入上一行的式子
b2 * x2 + (a2-(a2/b2)b2) * y2
=b2 * x2+a2
y1-(a2/b2)b2 * y2
=a2 * y2+b2
(x2-a2/b2 * y2)=gcd
發現 新的x=y2, 新的y=x2-a / b * y2

這就是相鄰兩層遞歸狀態x,y轉化的式子

求出了aa * xx+bb * yy=gcd(aa,bb)的一組解之後
aa * xx+bb * yy=m的一組解 就是xx * [m/gcd(aa,bb)]和yy * [m/gcd(aa,bb)]

對於ax+by=m:
gcd=gcd(a,b);
已經跑了exgcd後
((x*(m/gcd))%(b/gcd)+(b/gcd))%(b/gcd) (求x最小解的式子)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章