2020.02.15日常总结兼【模板】扩展中国剩余定理略讲

洛谷P4777   【模板】扩展中国剩余定理 \color{green}{\text{洛谷P4777\ \ \ 【模板】扩展中国剩余定理}}

\color{blue}{【题意】:}
在这里插入图片描述
\color{blue}{【输入输出样例及格式】:}
在这里插入图片描述
\color{blue}{【注意】:} 【分析与思路】中的 a , b a,b 与题意正好相反,请读者注意!!!

\color{blue}{【分析与思路】:} 假设我们已知前 k 1 k-1 个方程的解为 x x ,记 M = M=

Π i = 1 k 1 b i \Pi_{i=1}^{k-1} b_i

x + t × M x+t \times M 是前 k 1 k-1 个方程的通解。

于是,我们只需要找出一个 t t ,使得

x + t × M a i ( m o d b i ) x + t \times M ≡ a_i \pmod {b_i}

x = x + t × M x'=x+t \times M 即加入第 k k 个方程的解。

于是,我们只需循环 n n 次求解即可。

如何求 t t ?很简单,把方程移项,得:

t × M a i x ( m o d b i ) t \times M≡ a_i-x \pmod {b_i}

扩展gcd求解即可。

注意乘法时可能爆long long,需要用快速乘优化。

\color{blue}{【代码】:}

const int N=1e5+100;
ll exgcd(ll a,ll b,ll &x,ll &y){
	if (b==0){
		x=1;y=0;
		return a;
	}
	else{
		ll d=exgcd(b,a%b,y,x);
		y-=x*(a/b);return d;
	}
}
ll slow_mul(ll a,ll b,ll mod){
	register ll ret=0ll;
	while (b){
		if (b&1) ret=(ret+a)%mod;
		a=(a+a)%mod;b>>=1;
	}
	return ret;
}
ll a[N],b[N],M,ans,n;
int main(){
//	freopen("t1.in","r",stdin);
	n=read();M=1ll;ans=0;
	for(int i=1;i<=n;i++){
		b[i]=read();
		a[i]=read();
	}
	for(int i=1;i<=n;i++){
		ll B=((a[i]-ans)%b[i]+b[i])%b[i];
		ll t,y,GCD=exgcd(M,b[i],t,y);
		t=slow_mul(t,B/GCD,b[i]);
		ans+=M*t;
		M*=b[i]/GCD;
		ans=(ans+M)%M;
	}
	printf("%lld",ans);
	return 0;
}
发布了103 篇原创文章 · 获赞 4 · 访问量 6724

猜你喜欢

转载自blog.csdn.net/ZHUYINGYE_123456/article/details/104333518
今日推荐