P4777(扩展中国剩余定律,模板)

题意:https://www.luogu.org/problemnew/solution/P4777

解题思路:关于扩展中国剩余定理推导,看我其他的博客。

#include<bits/stdc++.h>
#define N 100009
#define ll long long
using namespace std;
ll a[N],b[N];
int n;
/*该方程 用于以下形式 
x=b1(mod a1)
x=b2(mod a2)
......
x=bn(mod an)*/
ll ex_gcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0){x=1,y=0;return a;}
	ll r=ex_gcd(b,a%b,y,x);
	y-=x*(a/b);
	return r;
}
/*ll ex_crt()
{
	ll M=a[0],R=b[0],x,y,d;//a是除数,也是答案 。b是被除的 
	for(int i=1;i<n;i++)
	{
		d=ex_gcd(M,a[i],x,y);
		if((b[i]-R)%d) return -1;//无解 
		x=(b[i]-R)/d*x%(a[i]/d);//计算系数 
		R+=x*M;//计算新X1的a,即特解 
		M=M/d*a[i];//LCM新的最小公倍数 
		R%=M;//由方程的原始形式可知,可以这么做。而且可以减小数字大小 
	}
	return R>0? R: R+M;
}*/
ll mul(ll x,ll y,ll mod)
{
	ll ans=0,res=x;
	while(y)
	{
		if(y&1) ans=(ans+res)%mod;
		y>>=1;
		res=(res+res)%mod;
	} 
	return ans;
}
ll ex_crt()
{
	ll M=a[0],R=b[0],x,y,d;//a是除数,也是答案 。b是被除的 
	for(int i=1;i<n;i++)
	{
		d=ex_gcd(M,a[i],x,y);
		ll c=((b[i]-R)%a[i]+a[i])%a[i];//其实就是扩大b[i],让b[i]>R.b[i]=b[i]+k*a[i] 
		if(c%d) return -1;//无解  
		x=mul(x,c/d,a[i]/d);
		R+=x*M;//计算新X1的a,即特解 
		M=M/d*a[i];//LCM新的最小公倍数 
		R%=M;//由方程的原始形式可知,可以这么做。而且可以减小数字大小 
	}
	return R>0? R: R+M;
}
int main()
{
	//freopen("t.txt","r",stdin);
	scanf("%d",&n); 
	for(int i=0;i<n;i++)
	{
		scanf("%lld%lld",&a[i],&b[i]);
	}
	printf("%lld",ex_crt()); 
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39861441/article/details/89154556