前言
1
(gcd(a,b)=gcd(b,a\%b),(gcd(a,0)=a))
小证一下吧
设 (d=gcd(a,b)) 则 (a=d*k,b=d*k')
当(a\%b!=0),则 (a\%b=a-leftlfloor dfrac ab ight floor * b = (k-leftlfloor dfrac ab ight floor*k')d) 并没有损失掉 (d)
当 (a\%b=0) 时,(b=gcd(a,b))
2
(a*x+b*y=c) 有解当且仅当 (gcd(a,b)|c)
这个就不多说了
exgcd
扩展欧几里得算法,求解出一组解 (x,y) 使得 (a*x+b*y=gcd(a,b))
我们当前有 (gcd(a,b)=gcd(b,a\%b),a\%b=a-leftlfloor dfrac ab ight floor * b)
用 (b) 代替 (a) , 用 (a\%b=a-leftlfloor dfrac ab ight floor * b) 代替 (b) 则原式成为
(b*x'+(a-leftlfloor dfrac ab ight floor * b)*y'=gcd(a,b)) 注意 (x' e x,y' e y)
我们大力化式子,差开 ((a-leftlfloor dfrac ab ight floor * b)*y)
原式变为
(b*x'+a*y'-b*leftlfloor dfrac ab ight floor*y'=gcd(a,b))
把 (a) 和 (b) 放到一起
(a*y'+b*(x'-leftlfloor dfrac ab ight floor*y')=gcd(a,b))
因此我们得出 , (x=y',y=x'-leftlfloor dfrac ab ight floor*y')
当我们求出 (gcd(a,b)) 时 (b=0) 此时 (a*x+b*y=a) 我们让 (x=1,y=0) 即可
这样反向推回去就行了
放下代码吧
int exgcd(int a,int b,int &x,int &y){
if(!b){ x=1,y=0; return a; }
int gcd=exgcd(b,a%b,y,x);
y-=a/b*x;
return gcd;
}
最后我们求得了 (a*x+b*y=gcd(a,b)) 如何求 (a*x+b*y=c) 呢?
让 (x,y) 分别乘上 (dfrac c{gcd(a,b)}) 就行了
现在我们已经求出了一组解 (x,y)如何得到另一组解 (x',y') 呢?
只需要让 (x'=x+dfrac{b}{gcd(a,b)},y'=y-dfrac{a}{gcd(a,b)}) 即可
证明
将 (x',y') 带入 (a*x+b*y=gcd(a,b)) 中 发现多出来的项消掉了
简单推导可知,这是 (x,y) 所能变动的最小范围
那么,我们知道了这个,就可以求出 (x) 的最小整数解,只需要让 (x\%dfrac b{gcd(a,b)}) 就行了
写公式好累啊,啊啊啊,就当复习了