扩展中国剩余定理

Posted 日拱一卒 功不唐捐

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了扩展中国剩余定理相关的知识,希望对你有一定的参考价值。

若有以下两个同余方程

x ≡ a1 mod n1

x ≡ a2 mod n2

x= n1*k1+a1 = n2*k2+a2

∴ n1*k1 = n2*k2+a2-a1

∴ n1*k1 ≡ a2-a1 mod n2

由扩展欧几里得定理得,同余方程有解的条件是 gcd(n1,n2) | (a2-a1)

令d=gcd(n1,n2),c=a2-a1

则n1/d * k1 ≡ c/d mod n2/d

∴ k1 = c/d * inv(n1/d)mod n2/d

令k=c/d * inv(n1/d),则k1 = k + (n2/d)*y

∴ x=n1*(k + (n2/d)*y)+a1

      =(n1*n2/d)*y+n1*k+a1

即 x ≡ n1*k+a1 mod  n1*n2/d

所以上面两个方程合并为 x ≡ a mod n

其中 a=n1*k+a1  n=n1*n2/d

 

#include<cstdio>
#include<iostream>

using namespace std;

typedef long long LL;

int n[11],a[11];

void read(int &x)
{
    x=0; char c=getchar();
    while(!isdigit(c)) c=getchar();
    while(isdigit(c)) { x=x*10+c-0; c=getchar(); }
}

int gcd(LL a,LL b,LL &x,LL &y)
{
    if(!b) { x=1; y=0; return a;}
    LL g=gcd(b,a%b,y,x); y-=a/b*x;
    return g;
}

int main()
{
    int T,m;
    read(T);
    LL a1,n1,a2,n2;
    LL d,c,k;
    LL x,y;
    while(T--)
    {
        read(m);
        for(int i=1;i<=m;++i) read(n[i]);
        for(int i=1;i<=m;++i) read(a[i]);
        bool tag=true;
        a1=a[1],n1=n[1];
        for(int i=2;i<=m;++i)
        {
            a2=a[i]; n2=n[i];
            d=gcd(n1,n2,x,y);
            c=a2-a1;
            if(c%d) { tag=false; break; }
            gcd(n1/d,n2/d,x,y);
            k=(x*c/d%(n2/d)+n2/d)%(n2/d);
            a1=(a1+n1*k)%(n1/d*n2);
            n1=n1/d*n2;
        }
        if(!tag) printf("No solution\n");
        else printf("%I64d\n",a1);
    }
}    

 

以上是关于扩展中国剩余定理的主要内容,如果未能解决你的问题,请参考以下文章

中国剩余定理与扩展中国剩余定理

中国剩余定理&&扩展中国剩余定理

中国剩余定理(CRT) & 扩展中国剩余定理(ExCRT)总结

欧几里得(辗转相除gcd)扩欧(exgcd)中国剩余定理(crt)扩展中国剩余定理(excrt)简要介绍

Acwing-204-表达整数的奇怪方式(扩展中国剩余定理)

中国剩余定理讲解