zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    调试 Android* x86 应用程序的方法以及要使用的工具
    android 获取手机信息工具类
    Android 布局自适应屏幕
    php &amp; 和 &amp;amp; (主要是url 问题)
    系统的BIOS与系统安装
    ios的设计原则
    POJ 2409 Let it Bead(Polya简单应用)
    鸿学金信风控具体介绍
    Linux高性能server编程——I/O复用
    WCF问题集锦:未依照DataMember定义的名称序列化对象
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9648301.html
Copyright © 2011-2022 走看看