拓展欧几里得
数论是学习OI的自闭之路。QAQ
问题如下:
求不定方程的整数解
ax+by=gcd(a,b)
的解。
通过欧几里得原理:
gcd(a,b)=gcd(b,a%b)
那么原式可化为:
bx′+a%by′=gcd(b,a%b)
那么只需求出x与x′,y与y′的关系即可:
bx′+a%by′=gcd(a,b)=gcd(b,a%b)=ax+by
将含a与含b的合并
bx′+a%by′=ax+bybx′+ay′−⌊ba⌋b×y′=ax+byb(x′−y−⌊ba⌋×y′)+a(y′−x)=0
已知该式恒成立,则:
xy=y′=x′−⌊ba⌋×y′
再利用辗转相除的函数递归计算x,y即可。
代码如下:
1 2 3 4 5 6 7 8 9 10
| int x,y;
int exgcd(int a,int b) { if(b==0) {x=1,y=0;return a;} int g=exgcd(b,a%b); int oldx=x,oldy=y; x=oldy; y=oldx-a/b*oldy; return g; }
|
这里需要注意的是,递归的边界为x=1,y=0时的一组特解。
那么将此式拓展为一般结论,即求解:
ax+by=c
首先讨论有无解,当gcd(a,b)∤c一定无解,这里就不给出证明。我们另k=gcd(a,b)c:
ax′k+by′k=gcd(a,b)×k=c
就得到了x=x′k,y=y′k。
如果要求x非负且最小,另t=gcd(a,b)b,则(x%t+t)%t就是x的最小非负解。加t主要是为了处理负数的问题。
有关例题: