0条评论
ax + by = c
先求出一组解, 然后考虑如何表示通解, 设d = gcd(a, b), 假设c不是d的倍数, 则左边是d的倍数而右边不是, 则方程无解, 所以方程有解当且仅当d | c.
设c = c’ * d, 我们先考虑方程 ax + by = d, 这样由扩展gcd便可求出一组解 (x’, y’), 则(c’x’, c’y’)就是原方程的一组解,然后考虑通解: ax = b(mod n)
其实方程等价于 ax - ny = b, 标准模线性方程,但是得考虑剩余系。
算法导论上有两个定理:
定理一:设d = gcd(a, n), 假定对整数x’, y’, 有d = ax’ + ny’, 如果d | b, 则方程ax = b(mod)有一个解的值为x0, 满足:、
x0 = x'(b / d)(mod n)
定理二:假设方程ax = b(mod n)有解, x0是方程的任意一个解, 则方程对模n恰有d个不同的解, 分别为: xi = x0 + i * (n / d), 其中 i = 1,2,3……d - 1
有了这两个定理, 解方程就不难了。
ll exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1;
y=0;
return a;
}
ll r=exgcd(b,a%b,x,y);
ll t=x;
x=y;
y=t-a/b*y;
return r;
}
bool linear_equation(ll a,ll b,ll c,ll &x,ll &y)
{
ll d=exgcd(a,b,x,y);
if(c%d)
return false;
ll k=c/d;
x*=k; y*=k; //求得的只是其中一组解
ll b1 = b/d;
ll a1 = a/d;
ll i = 0;
//cout<
if(y<0){
while (y<=0){
y+=a1;
x-=b1;
}
}
while (y-a1>=0){
y-=a1;
x+=b1;
}
if(y>=0&&x>=0){
return true;
} else{
return false;
}
}