模线性方程组

模线性方程组:
给定了n组除数m[i]和余数r[i],通过这n组(m[i],r[i])求解一个z,使得z % m[i] = r[i]

首先,从最简单的情况入手,只有两条方程:
设z%m0=r0, z%m1=r1;
=>z=r0+m0*k0, z=r1+m1*k1( k1,k2 为常数 )
=>r0+m0*k0=r1+m1*k1
=>m0*k0-m1*k1=r1-r0
设m0为A,m1为B,k0为x,-k1为y,r1-r0为C,则A*x+B*y=C;
所以很容易想到,这个可以用扩展欧几里德来求
求出x后,求出z0=r0+m0*k0=r0+m0*x
同时,我们将这个z0作为特解,可以扩展出一个解系:
Z = z0 + k*lcm(m0, m1) k为整数
化为方程式可以得到Z%lcm(m0, m1)=z0;
设M=lcm(m0, m1),R=z0,所以Z%M=R;
此时,可以发现我们将z mod m0= r0,z mod m1 = r1合并为了一个式子Z mod lcm(m0, m1) = z0。满足后者的X一定满足前两个式子。
每两个式子都可以通过该方法化简为一个式子。那么我们只要重复进行这个操作,就可以将n个方程组化简为一个方程,并且求出一个最后的解了。

模板:

#include
#include
#include
#include
using namespace std;
const int MAXN=15;
typedef long long LL;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    LL res=exgcd(b,a%b,x,y);
    LL tmp=x;
    x=y;
    y=tmp-a/b*y;
    return res;
}
LL solve(LL m[MAXN],LL r[MAXN],int n)
{
    LL x,y;
    LL M=m[0],R=r[0],C,gcd;
    for(int i=1;i

你可能感兴趣的:(模线性方程组)