模线性方程组

模线性方程组(中国余数定理)
题意:给定了n组除数m[i]和余数r[i],通过这n组(m[i],r[i])求解一个x,使得x mod m[i] = r[i]。

直接用中国余数定理,n个m[i]相乘,可能会超出longlong范围

做法:
从n=2开始递推
x mod m[1] = r[1]
x mod m[2] = r[2]
即存在
x = m[1] * k[1] + r[1]
x = m[2] * k[2] + r[2]
推出
m[1] * k[1] - m[2] * k[2] = r[2] - r[1]
可用扩展欧几里德求出k[1]进而求出x,那么
一开始的两个式子即可合并为
X mod lcm(m[1], m[2]) = x  (lcm为最小公倍数)

    for(i=1;i<=n;i++){
        scanf("%lld%lld",&m[i],&r[i]);
    }
    m[0]=m[1];
    r[0]=r[1];
    for(i=2;i<=n;i++){
        ll k1,k2,c;
        c=r[i]-r[0];
        ll gcd=ext_gcd(m[0],m[i],k1,k2);
        if(c%gcd){
            ans=-1;
            break;
        }
        m[i]/=gcd;
        c/=gcd;
        k1=(k1*c)%m[i];
        if(k1<0)
            k1+=m[i];
        r[0]=m[0]*k1+r[0];     // x
        m[0]=m[0]*m[i];        // 最小公倍数
        ans=r[0];
    }

你可能感兴趣的:(数论)