luogu4777[模板]拓展中国剩余定理题解

Posted rye-catcher

tags:

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

题目链接

https://www.luogu.org/problemnew/show/P4777

分析

扩展(CRT)就是解决模数不互质的情况,说是扩展(CRT),其实都是扩欧...

先来考虑两个方程的情况:(x equiv a mod b)(x equiv c mod d)

由方程1得(x=tb+a),代入方程2中得(tb+a equiv c mod d)

把它变得更像方程:(t imes b+t‘ imes d = c-a)

解得(t‘)后回代即可

那么对于多个方程组,假设对于前(k)个方程组我们已经求出一个解(x),记(M= prod_{i=1}^k m_i),那么显然(x+i imes M)是前(k)个方程的一个通解,因为(M equiv 0 mod m_i (i<=k))

那么我们要求的就是一个整数(t),使得(x+ t imes M equiv b _ {k+1} mod m _ {k+1})

移项得(t imes M + t‘ imes m _ {k+1} = b _ {k+1}- x)(这里的(x)其实是已知的)

运用扩欧算出(t),更新(x=x+t imes M),然后(M= M imes m _ {k+1})

当然无解的情况也就是扩欧无解的情况,当(b _ {k+1}-x)不整除(gcd(M,m _ {k+1}))时无解

注意

题目要求要将(x)化为最小整数解

代码

#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#define ll __int128
#define ri register int 
using std::min;
using std::max;
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=getchar()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn=100005;
const int inf=0x7fffffff;
ll b[maxn],m[maxn];
int 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-a/b*y;
    return d;
}
void print(ll x){
    if(!x) return;
    if(x) print(x/10);
    putchar(x%10+‘0‘);
}
ll ans=0;
int main(){
    ll x,y,M,aa,bb,cc,d;
    bool flag=0;
    read(n);
    for(ri i=1;i<=n;i++){
        read(m[i]),read(b[i]);
    }
    M=m[1],ans=b[1];
    for(ri i=2;i<=n;i++){
        aa=M,bb=m[i],cc=(b[i]-ans%bb+bb)%bb;
        x=0,y=0;
        //if(aa<bb) d=exgcd(bb,aa,x,y);
        //else d=exgcd(aa,bb,x,y);
        /*错误点:不要加if不然这样的话方程都改变了,感觉我是真的傻*/
        d=exgcd(aa,bb,x,y);
        bb=bb/d;
        if(cc%d){flag=1;break;}
        x=((x*cc/d)%bb+bb)%bb;
        /*错误点:要先×cc再除d,因为cc保证是d的倍数*/
        ans+=M*x;M*=bb;
        ans=(ans%M+M)%M;
    }
    if(flag)puts("-1");
    else {
        if(!ans)puts("0");
        else {print(ans);puts("");}
        //printf("%lld
",ans);
    }
    return 0;
}

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

LUOGU P4777 模板扩展中国剩余定理(EXCRT)

Luogu 4777 模板扩展中国剩余定理(EXCRT)

P4777 模板扩展中国剩余定理(EXCRT)

P4777 模板扩展中国剩余定理(EXCRT)

luogu P1495 曹冲养猪(中国剩余定理)

CF338D GCD Table(拓展中国剩余定理,细节处理,2900分)