中國剩餘定理

1. 模數互質的情況

LL n,m;
LL ai[N],bi[N];//餘數 模數
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    LL d=exgcd(b,a%b,x,y);
    LL z=x;
    x=y;
    y=z-y*(a/b);
    return d;
}
LL CRT()
{
    LL M=1,d,y,x,re=0;
    for(int i=1;i<=n;i++)
        M*=bi[i];
    for(int i=1;i<=n;i++)
    {
        LL k=M/bi[i];
        d=exgcd(k,bi[i],x,y);
        x=(x%bi[i]+bi[i])%bi[i];
        re=(re+ai[i]*x*k)%M;
    }
    return re;
}

2. 模數不互質的情況

LL n,m;
LL ai[N],bi[N];
LL exgcd(LL a,LL b,LL &x,LL &y)
{
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    LL d=exgcd(b,a%b,x,y);
    LL z=x;
    x=y;
    y=z-y*(a/b);
    return d;
}
LL EXCRT()
{
    LL x,y;
    LL M=bi[1],ans=ai[1];//數組從 1 讀入
    for(int i=2; i<=n; i++)
    {
        LL a=M,b=bi[i],c=(ai[i]-ans%b+b)%b;
        LL gcd=exgcd(a,b,x,y),bg=b/gcd;
        if(c%gcd!=0)
            return -1;//擴展歐幾里得判斷無解
        x=(x*(c/gcd)%bg+bg)%bg;
        ans+=x*M;
        M*=bg;
        //ans=(ans%M+M)%M;
    }
    return ans;
}

 

   2.1 如果爆longlong(_int 128 Linux環境下能夠使用

typedef __int128 LL;
inline __int128 read()
{
    __int128 x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        x=x*10+ch-'0';
        ch=getchar();
    }
    return x*f;
}
inline void print(__int128 x)
{
    if(x<0)
    {
        putchar('-');
        x=-x;
    }
    if(x>9)
        print(x/10);
    putchar(x%10+'0');
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章