zoukankan      html  css  js  c++  java
  • 【POJ2891】Strange Way to Express Integers

    题目大意:给定 M 组线性同余方程,要求将这 M 个同余方程合并成一个,并输出最小正整数解。

    题解:学会了扩展中国剩余定理。
    题目细节很多,需要对扩展欧几里得算法的通解理解透彻才能解决这个问题。QAQ

    根据数学归纳法,假设现在已经合并了前 (k-1) 个同余方程,现要合并第 (k) 个方程。

    [x+m*t equiv a_i mod b_i ]

    [t*m equiv a_i-x mod b_i ]

    根据扩展欧几里得算法可以求出系数 (t),再根据 (t) 进行合并即可。

    注意:

    • 洛谷的模板中需要用到乘法取模操作,在乘法取模时,若移位的是负数,会导致死循环,原因是移位的过程中,负数移位是算术移位,最高位补 1,就会导致死循环,因此需要将可能出现负数的地方变成正数。
    • 在系数调整的时候,需要进行取模操作,否则会爆 long long。

    代码如下

    #include <cstdio>
    using namespace std;
    typedef long long ll;
    
    ll exgcd(ll a,ll b,ll &x,ll &y){
    	if(!b)return x=1,y=0,a;
    	ll d=exgcd(b,a%b,x,y),z=x;
    	x=y,y=z-a/b*y;
    	return d;
    }
    
    ll n,ans,lcm,m,a,s,t;
    
    void excrt(){
    	int flag=0;
    	scanf("%lld%lld",&lcm,&ans);
    	while(--n){
    		scanf("%lld%lld",&m,&a);
    		ll c=((a-ans)%m+m)%m;
    		ll d=exgcd(lcm,m,s,t);
    		if(c%d)flag=1;
    		s=c/d*s%(m/d);// trap: overflow 
    		ans+=s*lcm,lcm=m/d*lcm,ans=(ans%lcm+lcm)%lcm;
    	}
    	if(flag)puts("-1");
    	else printf("%lld
    ",ans);
    }
    
    int main(){
    	while(scanf("%lld",&n)!=EOF)excrt();
    	return 0;
    }
    
  • 相关阅读:
    Freemarker list的使用
    Java通过流对MP4视频文件进行加密,H5 video播放流
    阿里云API公共参数的获取
    javah找不到类文件
    Java调用打印机打印指定路径图片
    Java绘制图片并进行合成
    Java生成二维码和解析二维码URL
    计算机网络第六版知识大纲
    Linux安装mysql mysql5.5.40 <NIOT>
    rsync unison+inotify双向实时同步
  • 原文地址:https://www.cnblogs.com/wzj-xhjbk/p/10730858.html
Copyright © 2011-2022 走看看