洛谷 P4774 [NOI2018] 屠龙勇士

题意经过化简,就是一个拓展拓展中国剩余定理了

给n个形如(Axequiv Bmod P)的同余方程,构成同余方程组

还是采用excrt合并的方式求解, 也就是所谓的扩展中国剩余定理

不同的地方在于,这里x前面有系数A,但对于excrt来说都一样

#include<bits/stdc++.h>
#define int __int128
using namespace std;

int rd(){
	int ret=0,f=1;char c;
	while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
	while(isdigit(c))ret=ret*10+c-'0',c=getchar();
	return ret*f;
}

const int MAXN = 100005;

int n,m;
int mx;

int a[MAXN],b[MAXN],p[MAXN];
int rwd[MAXN];

multiset<int> st;

void exgcd(int A,int B,int &x,int &y){
	if(B==0) x=1,y=0;
	else exgcd(B,A%B,y,x),y-=(A/B*x);	
}

int solve(){
	mx=0;
	st.clear();
	n=rd();m=rd();
	for(int i=1;i<=n;i++) b[i]=rd(); //life	
	for(int i=1;i<=n;i++) p[i]=rd(); 	
	for(int i=1;i<=n;i++) rwd[i]=rd();
	for(int i=1;i<=m;i++) st.insert(rd());	
	int preans=0,lcm=1;
	for(int i=1;i<=n;i++){
		auto cur=st.upper_bound(b[i]);
		if(cur!=st.begin()) cur--;
		a[i]=*cur;
		st.erase(cur);
		st.insert(rwd[i]);
		mx = max(mx, (b[i]-1)/a[i]+1);
	}
	for(int i=1;i<=n;i++){
		int g=__gcd(a[i]*lcm%p[i],p[i]),x,y;
		int c=b[i]-a[i]*preans%p[i];
		c%=p[i];
		if(c<0) c+=p[i];
		if((b[i]-a[i]*preans)%g) return -1;
		exgcd(a[i]*lcm%p[i],p[i],x,y);
		int stpx=p[i]/g;
		x%=stpx;
		if(x<0) x+=stpx;
		x*=(c)/g;
		if(x<0) x=-x;
		preans+=x*lcm;
		lcm*=p[i]/g;
		preans%=lcm;
		if(preans<0) preans+=lcm;
	}
	if(preans < mx) preans += ((mx-preans-1)/lcm+1) * lcm;
	return preans;
}

signed main(){
	int T=rd();
	while(T--){
		cout<<(long long)solve()<<endl;
	}
}

本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/15096388.html

原文地址:https://www.cnblogs.com/ghostcai/p/15096388.html