P3868(中国剩余定律入门)

                                                    

以上是中国剩余定律的适用问题(专门用于解线性同余方程)

题意描述:见https://www.luogu.org/problemnew/show/P3868

解题思路:参考https://www.luogu.org/problemnew/solution/P3868

我觉得要注意的地方有两点

1.快速乘可以防止爆long long。这个很有趣,以前一直用的都是快速幂,没想到快速乘有这种妙用。

2.ai可能存在负数,需要将其变成正数。其实如果不用快速乘倒是无所谓ai的正负。但是用了快速乘,ai必须得是正的,而且应该前面进行mod,可以减小快速乘的运算量。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a[15],b[15];
void exgcd(ll a,ll b,ll &x,ll &y)
{
	if(b==0) {x=1,y=0;return;}
	exgcd(b,a%b,x,y);
	ll t=x;
	x=y;
	y=t-a/b*y;
}
ll mul(ll x,ll b,ll mod)
{
	ll ans=0,res=x;
	while(b)
	{
		if(b&1) ans=(ans+res)%mod;
		b>>=1;
		res=(res+res)%mod;
	}
	return ans;
}
int main()
{
	//freopen("t.txt","r",stdin);
	int k;
	scanf("%d",&k);
	ll sum=1;
	for(int i=0;i<k;i++) scanf("%lld",&a[i]);
	for(int i=0;i<k;i++) scanf("%lld",&b[i]),sum*=b[i];
	for (int i=0; i<k;i++) a[i]=((a[i]%b[i])+b[i])%b[i];
	ll x,y,ans=0;
	for(int i=0;i<k;i++)
	{
		ll t=sum/b[i];
		exgcd(t,b[i],x,y);
		x=(x%b[i]+b[i])%b[i];
		//ans=(ans+t*a[i]*x)%sum;
		ans=(ans+mul(mul(t,a[i],sum),x,sum))%sum;
	}
	cout<<ans;
	return 0;
 } 

猜你喜欢

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