【题解】[NOI2018] 屠龙勇士
\(\text{Solution:}\)
确实是送分题……但细节也确实多……找个好板子很重要
容易得出来就是求一堆形如 \(vx\equiv a_i(\bmod p_i)\) 的方程组,但有很多细节:
首先是,这没有保证模数互质,所以需要扩展中国剩余定理
其次,模数很大,需要快速乘
inline int QMul(int a,int b,int p){
a%=p;b%=p;
int c=(long double)a*b/p;
int x=a*b,y=c*p;
int res=(int)(x%p)-(int)(y%p);
if(res<0)res+=p;return res;
}
还有,取模一定要处理好,原本的代码找了好久不知道为什么判错了,打算换一个板子背了
要求的解并不是最小整数解,还需要满足使得 \(vx\ge a_i\)
找后继的时候如果用 multiset
一定用 \(s.lower_bound\) 而不是其他的,用迭代器那个复杂度是 \(O(n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int T,n,m,b[N],t[N];
typedef long long ll;
ll a[N],p[N],mx;
multiset<ll>s;
inline int Max(int x,int y){return x>y?x:y;}
void Exgcd(ll a,ll b,ll &x,ll &y,ll &d){
if(!b){x=1,y=0;d=a;}
else Exgcd(b,a%b,y,x,d),y-=(a/b)*x;
}
ll ExCRT(){
ll ans=0,lcm=1,A,B,C,G,x,y;
for(int i=1;i<=n;++i){
A=(__int128)b[i]*lcm%p[i];
B=p[i],C=(a[i]-b[i]*ans%p[i]+p[i])%p[i];
Exgcd(A,B,x,y,G);x=(x%p[i]+p[i]%p[i]);
if(C%G)return -1;
ans+=(__int128)(C/G)*x%(B/G)*lcm%(lcm*=B/G);
ans%=lcm;
}
if(ans<mx)ans+=((mx-ans-1)/lcm+1)*lcm;
return ans;
}
int main(){
cin>>T;
while(T--){
s.clear();
cin>>n>>m;mx=0;
for(int i=1;i<=n;++i)cin>>a[i];
for(int i=1;i<=n;++i)cin>>p[i];
for(int i=1;i<=n;++i)cin>>t[i];
for(int i=1;i<=m;++i){
int x;cin>>x;
s.insert(x);
}
for(int i=1;i<=n;++i){
auto u=s.upper_bound(a[i]);
if(u!=s.begin())--u;
b[i]=*u;s.erase(u);s.insert(t[i]);
mx=Max(mx,(a[i]-1)/b[i]+1);
}
printf("%lld\n",ExCRT());
}
return 0;
}