原文链接https://www.cnblogs.com/zhouzhendong/p/NOI2018Day2T1.html
题目传送门 - 暂无
题意
题解
首先我们仔细看一看样例可以发现如果一回合打不过巨龙就输了。
所以每一回合都要赢。所以每一次选择的宝剑都是可以提前预知的。
我们用个 set 来支持快速插入和 upper_bound ,可以在 $O((n+m)\log m)$ 的时间复杂度内处理得到每一把宝剑要处理的巨龙。
我们考虑化简一下原题的意思:
令 $v_i$ 为攻击第 $i$ 只龙的宝剑的攻击力。
则对于最终答案 $x$ 必然满足:
$$\forall i\in \{1,2,\cdots,n\}$$
扫描二维码关注公众号,回复:
2266861 查看本文章
$$a_i\leq x\times v_i$$
$$a_i\equiv x\times v_i\pmod {p_i}$$
代码
#include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <vector> #include <set> #include <queue> using namespace std; typedef long long LL; bool isd(char ch){ return '0'<=ch&&ch<='9'; } LL read(){ LL x=0; char ch=getchar(); while (!isd(ch)) ch=getchar(); while (isd(ch)) x=(x<<1)+(x<<3)+ch-48,ch=getchar(); return x; } const int N=100005; int T,n,m; LL a[N],p[N],h[N],v[N],x[N]; multiset <LL> S; LL ex_gcd(LL a,LL b,LL &x,LL &y){ if (!b){ x=1,y=0; return a; } LL res=ex_gcd(b,a%b,y,x); y-=x*(a/b); return res; } LL gcd(LL a,LL b){ return b?gcd(b,a%b):a; } LL inv(LL v,LL p){ LL x,y,g=ex_gcd(v,p,x,y); if (g>1) return -1; return (x+p)%p; } LL Mul(LL a,LL b,LL p){ a=(a%p+p)%p; b=(b%p+p)%p; LL ans=0; for (;a;a>>=1,b=(b<<1)%p) if (a&1LL) ans=(ans+b)%p; return ans; } bool CRT(LL w1,LL p1,LL w2,LL p2,LL &w,LL &p){ LL x,y,z=w2-w1,g=ex_gcd(p1,p2,x,y); if (z%g) return 0; LL t=z/g; x=Mul(x,t,p2/g); p=p1/g*p2; w=((w1+Mul(x,p1,p))%p+p)%p; return 1; } LL Solve(){ n=read(),m=read(); for (int i=1;i<=n;i++) a[i]=read(); for (int i=1;i<=n;i++) p[i]=read(); for (int i=1;i<=n;i++) h[i]=read(); S.clear(); while (m--) S.insert(read()); for (int i=1;i<=n;i++){ multiset <LL> :: iterator p=S.begin(); if ((*p)<a[i]) p=--S.upper_bound(a[i]); v[i]=*p,S.erase(p); S.insert(h[i]); } for (int i=1;i<=n;i++){ LL g=gcd(a[i],gcd(v[i],p[i])); v[i]/=g,p[i]/=g,a[i]/=g; LL Inv=inv(v[i],p[i]); if (Inv<0) return -1LL; x[i]=Mul(a[i],Inv,p[i]); } LL W=x[1],P=p[1]; for (int i=2;i<=n;i++) if (!CRT(W,P,x[i],p[i],W,P)) return -1LL; // x = W (mod P) for (int i=1;i<=n;i++){ LL val=(a[i]+v[i]-1)/v[i]; if (val<=W) continue; LL k=(val-W+P-1)/P; W+=k*P; } return W; } int main(){ freopen("dragon.in","r",stdin); freopen("dragon.out","w",stdout); scanf("%d",&T); while (T--) printf("%lld\n",Solve()); fclose(stdin);fclose(stdout); return 0; }