洛谷 P3868 [TJOI2009]猜数字


题意简述

给定\(a[1],a[2],\cdots,a[n]\)\(b[1],b[2],\cdots,b[n]\),其中\(b\)中元素两两互素。
求最小的非负整数\(n\),满足对于任意的\(i\)\(n - a[i]\)能被\(b[i]\)整除。

题解思路

变形后用中国剩余定理即可,注意要快速乘。

代码

#include 
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
ll n,x,y,lcm=1,ans;
ll a[15],p[15];
inline ll _mul(ll x,ll y,ll p) {
    ll z=(ld)x/p*y;
    ll res=(ull)x*y-(ull)z*p;
    return (res+p)%p;
}
void exgcd(const ll& a,const ll& b,ll& x,ll& y) {
	if (!b) { x=1; y=0; return; }
	exgcd(b,a%b,x,y);
	ll tmp=y; y=x-(a/b)*y; x=tmp;
}
int main() {
	scanf("%lld",&n);
	for (register int i=1;i<=n;++i) scanf("%lld",&a[i]);
	for (register int i=1;i<=n;++i) scanf("%lld",&p[i]),lcm*=p[i];
	for (register int i=1;i<=n;++i)	a[i]=(a[i]%p[i]+p[i])%p[i];
	for (register int i=1;i<=n;++i) {
		ll xx=lcm/p[i]; exgcd(xx,p[i],x,y);
		x=(x%p[i]+p[i])%p[i];
		(ans+=_mul(_mul(x,xx,lcm),a[i],lcm))%=lcm;
	}
	printf("%lld\n",ans);
}