zoukankan      html  css  js  c++  java
  • 【模板】扩展中国剩余定理(EXCRT)

    洛咕

    题意:(left{egin{aligned}xequiv a_1(mod b_1) quad\ xequiv a_2(mod b_2) quad\ xequiv a_3(mod b_3) quad\ ...quad\xequiv a_n(mod b_n) quadend{aligned} ight.)

    其中(b_1,b_2,b_3...b_n)不一定两两互质,求x的最小非负整数解.

    分析:中国剩余定理中(b_1,b_2,b_3...b_n)保证了两两互质,而扩展中国剩余定理中没有,所以它们两个没有半毛钱关系.扩展中国剩余定理只需要用到扩展欧几里得(广告).

    假设已经求出前k-1个方程组成的同余方程组的一个解为ans,且有(M=prod_{i=1}^{k-1}b_i)(这里理解为最小公倍数),则前k-1个方程构成的方程组的通解为(ans+p*M(pin Z))

    那么对于前k个方程构成的方程组,我们就是要求一个正整数q,使得(ans+q*M equiv a_k(mod b_k)).

    移项得(q*M equiv a_k-ans(mod b_k))

    如果你理解了扩展欧几里得算法的话,看到上面这个式子应该会感到很亲切.

    我们令(c=a_k-ans),则我们要求的就是(q*M equiv c(mod b_k)),即求出(gcd=exgcd(M,b_k,x,y)),如果gcd不是c的约数,则该方程无解,则整个同余方程组无解.

    若方程有解,则(x*(c/gcd))就是方程(q*M equiv c(mod b_k))的解,则前i个方程构成的方程组的解就是(ans+[x*(c/gcd)]*M).

    综上我们只要跑k次扩展欧几里得就行了.然后洛咕上这道题相乘的时候会爆long long,要用到龟速乘.

    #include<bits/stdc++.h>
    #define rg register
    #define LL long long 
    using namespace std;
    inline LL read(){
        rg LL s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){s=s*10+ch-'0';ch=getchar();}
        return s*w;
    }
    LL n,a[100005],b[100005];
    inline 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,y,x);
        y-=x*(a/b);
        return d;
    }
    inline LL quickmul(LL a,LL b,LL c){//龟速乘
        LL cnt=0;
        while(b){
    		if(b&1)cnt=(cnt+a)%c;
    		a=(a+a)%c;
    		b>>=1;
        }
        return cnt%c;
    }
    inline LL ex_intchina(){//模板
        LL ans=a[1],M=b[1];
        for(int i=2;i<=n;i++){
    		LL c=((a[i]-ans)%b[i]+b[i])%b[i];
    		LL x,y,gcd=exgcd(M,b[i],x,y);
    		if(c%gcd!=0)return -1;
    		x=quickmul(x,c/gcd,b[i]);
    //当前第i个方程的解
    		ans+=x*M;
    //更新前i个方程组的解ans
    		M*=b[i]/gcd;
    //更新M(所有模数的最小公倍数)
    		ans=(ans%M+M)%M;
        }
        return ans;
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++){
    		b[i]=read();a[i]=read();
        }//转换一下输入,我习惯b[i]是模数
        printf("%lld
    ",ex_intchina());
        return 0;
    }
    
    
  • 相关阅读:
    教程:在 Visual Studio 中开始使用 Flask Web 框架
    教程:Visual Studio 中的 Django Web 框架入门
    vs2017下发现解决python运行出现‘No module named "XXX""的解决办法
    《sqlite权威指南》读书笔记 (一)
    SQL Server手工插入标识列
    hdu 3729 I'm Telling the Truth 二分图匹配
    HDU 3065 AC自动机 裸题
    hdu 3720 Arranging Your Team 枚举
    virtualbox 虚拟3台虚拟机搭建hadoop集群
    sqlserver 数据行统计,秒查语句
  • 原文地址:https://www.cnblogs.com/PPXppx/p/10547175.html
Copyright © 2011-2022 走看看