参见:维基百科
线性同余方程组的求解可以分解为求若干个线性同余方程。比如,对于线性同余方程组:
- 2x ≡ 2 ( mod 6)
- 3x ≡ 2 ( mod 7)
- 2x ≡ 4 ( mod 8)
首先求解第一个方程,得到x ≡ 1 (mod 3),于是令x = 3k + 1,第二个方程就变为:
- 9k ≡ −1 ( mod 7)
解得k ≡ 3 (mod 7)。于是,再令k = 7l + 3,第三个方程就可以化为:
- 42l ≡ −16 ( mod 8)
解出:l ≡ 0 (mod 4),即 l = 4m。代入原来的表达式就有x = 21(4m) + 10 = 84m + 10,即解为:
- x ≡ 10 ( mod 84)
对于一般情况下是否有解,以及解得情况,则需用到数论中的中国剩余定理。
代码:
typedef long long int64;
int64 a[10000],b[10000];
void exgcd(int64 a,int64 b,int64 &d,int64 &x,int64 &y)
{
if(!b)
{
d=a;
x=1;
y=0;
}
else
{
exgcd(b,a%b,d,y,x);
y-=a/b*x;
}
}
int64 solve(int n) //x=b[i](mod a[i])
{
int64 ta=a[0],tb=b[0];
bool flag=true;
for(int i=1; i<n; i++)
{
int64 xa=ta,xb=a[i],c=b[i]-tb,d,x,y;
exgcd(xa,xb,d,x,y);
if(c%d)
{
flag=false;
break;
}
int64 tmp=xb/d;
x=(x*(c/d)%tmp+tmp)%tmp;
tb=ta*x+tb;
ta=ta/d*a[i];
}
if(!flag) //方程组无解
return -1;
return tb;
}
另外:这里所求的解小于LCM(b数组所有元素)且非负数,即最小非负整数解。设b数组所有元素的最小公倍数为LCM,最小非负整数解为X0,则通解:X=x0+LCM*k,其中k为整数。