求不定方程 a∗x+b∗y=1 的一组解的方法
由 a∗x1+b∗y1=gcd(a,b)=gcd(b,amod b)=b∗x2+[a−⌊a/b⌋∗b]∗y2=a∗y2+b∗(x2−y2∗⌊a/b⌋)
=>x1=y2
=>y1=x2−y2∗(a / b)
用途:
1)求解不定方程;
2)求解模线性方程(线性同余方程);
3)求解模的逆元;
1)求解不定方程
利用扩展欧几里得算法求解不定方程a∗x+b∗y=n的整数解的求解全过程,步骤如下:
(1)先计算Gcd(a,b),若n不能被Gcd(a,b)整除,则方程无整数解;否则,在方程两边同时除以Gcd(a,b),得到新的不定方程a2∗x+b2∗y=n2此时Gcd(a2,b2)=1;
(2)利用扩展欧几里德算法求出方程a2∗x+b2∗y=1的一组整数解x0,y0,则n2∗x0,n2∗y0是方程a2∗x+b2∗y=n2的一组整数解;
(3)根据数论中的相关定理,可得方程a2∗x+b2∗y=n2的所有整数解为:
x=n2∗x0+b2∗t
y=n2∗y0−a2∗t (t=0,1,2,……)
调整得到正整数解
LL exgcd(LL a, LL b, LL &x, LL &y) {
if(!b) {
x = 1;
y = 0;
return a;
}
LL ans = exgcd(b, a%b, x, y);
LL temp = x;
x = y;
y = temp - a / b * y;
return ans;
}
LL cal(LL a, LL b, LL c) {
LL x, y;
LL gcd = exgcd(a, b, x, y);
if(c % gcd != 0) return -1;
x *= c / gcd;
b /= gcd;
if(b < 0) b =- b;
LL ans = x % b;
if(ans <= 0) ans += b;
return ans;
}
数学一本通:注释此代码来自课本,未经测试,编译没问题
/*ax+by=GCD(x,y)->ax+(x-a/b*q)*b正向递归,返回时相应元素一一对应 */
#include<cstdio>//ax+by=GCD(a,b)
using namespace std;
int extended_gcd(int a, int b, int &x, int &y)
{
int ret,temp;
if (!b)
{
x = 1;
y = 0;
return a;//整个的最终函数返回的的值,最大公约数
}
extended_gcd(b, a%b, x, y);
temp = x;
x = y;
y = temp - a / b * y;
return ret;//递归逐步返回的公约数
}
int main()
{
int a, b, x, y, z;
scanf("%d%d", &a, &b);
z = extended_gcd(a, b, x, y);
printf("%d%d%d", z, x, y);//输出最大公约数和一组解
return 0;
}