Luogu-4774 [NOI2018]屠龍勇士
阿新 • • 發佈:2018-11-27
這題好像只要會用set/平衡樹以及裸的\(Excrt\)就能A啊...然而當時我雖然看出是\(Excrt\)卻並不會...今天又學了一遍\(Excrt\),趁機把這個坑給填了吧
現預處理一下,找出每條龍用哪吧劍,把所有龍都砍\(tmp\)刀到負血。
設之後每條龍都砍了a刀,對於第\(i\)條龍,劍的攻擊力為\(w_i\),恢復能力為\(c_i\),血量為\(b_i\)
則根據題意,滿足
\[ b_i-aw_i+yc_i=0 \]
\[ aw_i\equiv b_i(mod\ c_i) \]
將\(w_i,b_i,c_i\)同時除以\(gcd(w_i,c_i)\)然後
\[ a\equiv b_iinv(w_i)(mod\ c_i) \]
這道題就變成了同餘方程組求解:
\[ \begin{cases} a\equiv b_1inv(w_1)(mod\ c_1)\\ a\equiv b_2inv(w_2)(mod\ c_2)\\ ...\\ a\equiv b_ninv(w_n)(mod\ c_n)\\ \end{cases} \]
解出\(a\),答案就是\(a+tmp\)
程式碼
#include<map> #include<set> #include<cmath> #include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; typedef multiset<ll> MT; const int maxn=1e5+100; int n,m; ll b[maxn],c[maxn],w[maxn],a,bi,ci,k[maxn],sxz[maxn]; bool err; MT st; ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} void exgcd(ll a,ll b,ll &x,ll &y){b?(exgcd(b,a%b,y,x),y-=a/b*x):(x=1,y=0);} ll inv(ll a,ll b){ll x,y; exgcd(a,b,x,y); return (x%b+b)%b;} ll e(ll a,ll b,ll p){ ll x=a*b-(ll)((long double)a*b/p+0.5)*p; return x<0?x+p:x; } void excrt(ll bj,ll cj){ if(bi==0&&ci==0){ bi=bj,ci=cj; return; } ll C=bj-bi,d=gcd(ci,cj),P=ci/d*cj; if(C%d!=0){err=1; return;} ll K=e(C/d%(cj/d),inv(ci/d,cj/d),(cj/d)); bi=(e(K,ci,P)+bi)%P,ci=P; } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&b[i]); for(int i=1;i<=n;i++) scanf("%lld",&c[i]); for(int i=1;i<=n;i++) scanf("%lld",&w[i]); for(int i=1;i<=n;i++) st.clear(),bi=ci=0,err=0; for(int i=1;i<=m;i++) scanf("%lld",&a),st.insert(a),sxz[i]=a; sort(sxz+1,sxz+m+1); ll tp=0; for(int i=1;i<=n;i++){ MT::iterator p=st.lower_bound(b[i]); if(p==st.end()||(p!=st.begin()&&*p>b[i])) p--; k[i]=*p,tp=max(tp,(b[i]-1)/k[i]+1); st.erase(p); st.insert(w[i]); } for(int i=1;i<=n;i++){ b[i]-=tp*k[i],b[i]=(b[i]%c[i]+c[i])%c[i]; int lp=gcd(k[i],c[i]); if(b[i]%lp!=0){ err=1; break; } c[i]/=lp,b[i]/=lp,k[i]/=lp; b[i]=e(b[i],inv(k[i],c[i]),c[i]); } for(int i=1;i<=n;i++){ excrt(b[i],c[i]); if(err) break; } if(err) printf("-1\n"); else printf("%lld\n",(bi%ci+ci)%ci+tp); } return 0; }