一个不用中国剩余定理求解线性同余方程组的方法。
现在我们有x = b1(mod m1), x = b2(mod m2) ... x = bn(mod mn) 求解一个最小的使其满足上述方程,我们首先考虑x = b1 (mod m1), x = b2 (mod m2)这两个方程, 如果我们用这两个方程求出了一个解x0, 那么其一个解为x = x0 mod([m1, m2]), 通过这个办法我们将两个方程合成一个方程。 对于n个方程我们进行n-1次操作即可就出方程组的解。 现在思考如何将两个方程合并成为一个方程, x = b1(mod m1) => x = b1 + m1*y x = b2(mod m2) => x = b2 + m2*z 合并两式得到m1*y-m2*z=b2-b1,现在就可以用egcd求出一个解, 然后就可以顺利求出x了。代码如下:
#include <cstdio> #include <algorithm> #include <cstring> #include <iostream> using namespace std; typedef long long LL; LL gcd(LL a, LL b) { if(!b) return a; else return gcd(b, a%b); } LL lcm(LL a, LL b) { return a/gcd(a, b)*b; } void egcd(LL a, LL b, LL &d, LL &x, LL &y) { if(!b) { d=a; x=1; y=0; } else { egcd(b, a%b, d, y, x); y -= x*(a/b); } } LL solve(LL bb[], LL m[], int len) //返回最小解 { for(int i=1; i<len; i++) { LL g, x, y; LL a=m[0], b=-m[i], c=bb[i]-bb[0]; egcd(a, b, g, x, y); if(c%g != 0) return -1; //此时无解 x = c/g*x; x = m[0]*x + bb[0]; m[0]=lcm(m[0], m[i]); bb[0]=(x%m[0]+m[0])%m[0]; } return bb[0]; } int main() { int len; LL bb[100], m[100]; cin>>len; for(int i=0; i<len; i++) { cin>>bb[i]>>m[i]; } cout<<solve(bb, m, len)<<endl; return 0; }