• [luogu 4777] exCRT


    题目传送-Luogu4777

    题目传送-POJ2891

    题意:

    给若干同余方程组

    [egin{cases}x&equiv&x_1&pmod {p_1}\x&equiv&x_2&pmod {p_2}\ &&vdots\x&equiv&x_n&pmod {p_n}end{cases} ]

    求最小的非负整数解(x),如果无解输出(-1)

    题解:

    exCRT裸题,算法学习见->我的另一篇博客

    过程:

    luogu:部分操作需要用到快速乘
    POJ:多组数据+禁止__gcd+不告诉你n=100000

    代码:

    只给出luogu代码

    const int N=100010;
    int n;
    inline void exgcd(ll a,ll b,ll &x,ll &y) {if(!b) {x=1; y=0; return;} exgcd(b,a%b,y,x); y-=a/b*x;}
    inline ll lcm(ll a,ll b) {return a/__gcd(a,b)*b;}
    inline ll Up(ll x,ll y) {return x/y+(x%y!=0);}
    inline ll Mul(ll x,ll y,ll P) {
    	// printf("%lld %lld %lld
    ",x,y,P);
    	ll ret=0; y%=P;
    	for(;y;y>>=1,x=x+x) {
    		// puts("?");
    		if(x>=P) x-=P;
    		if(y&1) {
    			ret=ret+x;
    			if(ret>=P) ret-=P;
    		}
    	}
    	return ret;
    }
    struct FUNCTION {
    	ll k,r;
    	inline void in() {
    		read(k); read(r);
    	}
    }f[N];
    bool fl=1;
    inline FUNCTION Merge(FUNCTION a,FUNCTION b) {
    	ll z=b.r-a.r,x1,x2,g=__gcd(a.k,b.k); exgcd(a.k,b.k,x1,x2);
    	if(z%g!=0) {puts("-1"); fl=0; return;} ll tim=z/g;
    	if(tim<0) {x1=-x1; tim=-tim;}
    	if(x1<0) {
    		ll add=b.k/g;
    		x1+=add*Up(-x1,add);
    		// assert(x1>=0);
    	}
    	// assert(x1>=0);
    	FUNCTION ret;
    	ret.k=lcm(a.k,b.k);
    	ret.r=Mul(a.k,Mul(x1,tim,ret.k),ret.k)+a.r;
    	// assert(ret.r>=0);
    	return ret;
    }
    signed main() {
    	read(n);
    	for(int i=1;i<=n;i++) f[i].in();
    	for(int i=2;i<=n;i++) {
    		f[1]=Merge(f[1],f[i]);
    		if(!fl) return 0;
    	}
    	printf("%lld
    ",f[1].r);
    	return 0;
    }
    

    用时:30min

  • 相关阅读:
    最大子数组1
    大道至简阅读笔记03
    I-think-3
    第3周学习进度
    大道至简阅读笔记02
    四则运算题3
    大道至简阅读笔记01
    第2周学习进度
    构建之法阅读笔记03
    按Right-BICEP的测试用例
  • 原文地址:https://www.cnblogs.com/functionendless/p/9445650.html
Copyright © 2020-2023  润新知