模线性方程组(中国剩余定理+通用解法)

版权声明:本文为博主原创文章,请随意转载(注明出处)。 https://blog.csdn.net/can919/article/details/82349940

求解

{ x a 1   ( m o d   m 1 ) x a 2   ( m o d   m 2 ) x a 3   ( m o d   m 3 ) . . . x a n   ( m o d   m n )

中国剩余定理

m 1 , m 2 , m 3 , . . . , m n 两两互质,则可用中国剩余定理

M = i = 1 n m i M i = M / m i t i M i ( m o d   m i ) 意义下的逆元,那么通解为

x = k M + i = 1 n a i t i M i

解释一下: 懒得证
因为 t i M i 1   ( m o d   m i ) ,而 M j 0   ( m o d   m i )   ( j i ) ,所以整个求和式子中,模 m i 有用的就只剩下 a i t i M i a i   ( m o d   m i ) ,对每一个 m i 都如此,满足所有条件。

通用解法

不要求 m 1 , m 2 , m 3 , . . . , m n 两两互质的解法

首先考虑只有两个方程

{ x a 1   ( m o d   m 1 ) x a 2   ( m o d   m 2 )


{ x = a 1 + m 1 k 1 x = a 2 + m 2 k 2

a 1 + m 1 k 1 = a 2 + m 2 k 2

m 1 k 1 m 2 k 2 = a 2 a 1

用exgcd求不定方程,将 k 1 k 2 解出,并带入原方程,得到一个特解 x
可知这两个方程的通解 X
X = x + t × l c m ( m 1 , m 2 )


X x   ( m o d   l c m ( m 1 , m 2 )   )

我们已经成功把两个方程合为一个,只需要继续把这个方程与方程组其他方程一一合并,就求出解了

模板题

HDU1573,求解的个数

#include<cstdio>
const int MAXM=13;
long long gcd(long long a,long long b,long long &x,long long &y)
{
    if(b==0)
    {
        x=1;y=0;
        return a;
    }
    long long xx,yy,d=gcd(b,a%b,xx,yy);
    x=yy;
    y=xx-a/b*yy;
    return d;
}
long long a[MAXM],b[MAXM];
int main()
{
    int T,M;
    long long N,A,B,d,l,x,y,p,q,r;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%I64d%d",&N,&M);
        for(int i=1;i<=M;i++)
            scanf("%I64d",a+i);
        for(int i=1;i<=M;i++)
            scanf("%I64d",b+i);
        A=a[1];B=b[1];
        bool flag=true;
        for(int i=2;i<=M;i++)
        {
            p=A;q=a[i];r=b[i]-B;
            d=gcd(p,q,x,y);
            if(r%d)
            {flag=false;break;}
            p/=d;q/=d;r/=d;
            x=x*r;
            x=(x%q+q)%q;
            l=A/d*a[i];
            B=x*A+B;
            B=(B%l+l)%l;
            A=l;
            if(B>N)break;
        }
        if(flag&&B<=N)
            printf("%I64d\n",(N-B)/A+(B!=0));
        else
            puts("0");
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/can919/article/details/82349940