【題解】[NOI2018] 屠龍勇士
阿新 • • 發佈:2021-10-07
\(\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\gep 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; }