gcd
- gcd有两种求法:gcd(a, b)=gcd(b, a%b)=gcd(a-b, b)
扩展gcd(一种新的写法)
- 找出一对整数\((x, y)\)使得\(ax+by=gcd(a,b)\)
void exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1;
y = 0;
return ;
}
exgcd(b, a%b, y, x);//x'=y, y'=x
y-=(a/b)*x;
return ;
}
- 代码如上,但是这是如何得出的呢?我们来推导一下
- \(ax+by=d, bx'+(a mod b)y'=d\)
\(bx'+(a-\left\lfloor\frac{a}{b}\right\rfloor·b)y'=d\)
\(bx'+ay'-\left\lfloor\frac{a}{b}\right\rfloor·by'=d\)
\(ay'+b(x'-\left\lfloor\frac{a}{b}\right\rfloor·y')=d\)
\(x=y', y=x'-\left\lfloor\frac{a}{b}\right\rfloor·y'\)
- 然后就变成了求\(bx'+(a mod b)y'=d\)
- 坚持不懈的递归下去,总能找到b=0的时候,然后就能求x'和y',再代回去就OK啦!
- 不理解也没问题,老师说代码背会就OK!
- 上面那个好背哦,但是难理解,下面这个就是【真·直译】
void exgcd(int a, int b, int &x, int &y)
{
if(!b)
{
x = 1;
y = 0;
return ;
}
exgcd(b, a%b, x, y);
int temp;
temp = x;
x = y;
y = temp-(a/b)*y;
return ;
}
- OK完美!但是只有这样吗?
- 当然不是。解不一定只有这一种,为了求出更多的解:\(ax_1+by_1=ax_2+by_2=d\)
移项\(\Rightarrow a(x_1-x_2)=b(y_2-y_1)\)
除d\(\Rightarrow a'(x_1-x_2)=b'(y_2-y_1), a'=a/d, b'=b/d\)
显然,a'与b'互质,\(\therefore x_1-x_2=kb', y_2-y_1=ka'\)
\(\therefore x_2=x_1-kb', y_2=y_1+ka'(k\in Z)\)
客串一个裴蜀定理
- \(ax+by=c\)有解,当且仅当\(gcd(a, b)|c\)
令\(c=gcd(a,b)·k\),两边同除k得\(a(x/k)+b(y/k)=gcd(a,b)\)
令\(x'=x/k, y'=b/k; \therefore ax'+by'=gcd(a,b)\)
显然我们能求出\(x', y'\),因此也能求出原来的解。