题目描述
小D 最近在网上发现了一款小游戏。游戏的规则如下:
-
游戏的目标是按照编号1→n1 \rightarrow n1→n 顺序杀掉nnn 条巨龙,每条巨龙拥有一个初始的生命值aia_iai 。同时每条巨龙拥有恢复能力,当其使用恢复能力时,它的生命值就会每次增加 pip_ipi ,直至生命值非负。只有在攻击结束后且当生命值恰好为 000 时它才会死去。
-
游戏开始时玩家拥有mmm 把攻击力已知的剑,每次面对巨龙时,玩家只能选择一 把剑,当杀死巨龙后这把剑就会消失,但作为奖励,玩家会获得全新的一把剑。 小D 觉得这款游戏十分无聊,但最快通关的玩家可以获得ION2018 的参赛资格, 于是小D 决定写一个笨笨的机器人帮她通关这款游戏,她写的机器人遵循以下规则:
-
每次面对巨龙时,机器人会选择当前拥有的,攻击力不高于巨龙初始生命值中攻击力最大的一把剑作为武器。如果没有这样的剑,则选择攻击力最低的一把剑作为武器。
-
机器人面对每条巨龙,它都会使用上一步中选择的剑攻击巨龙固定的xxx 次,使巨龙的生命值减少x×ATKx \times ATKx×ATK 。
-
之后,巨龙会不断使用恢复能力,每次恢复pip_ipi 生命值。若在使用恢复能力前或某一次恢复后其生命值为000 ,则巨龙死亡,玩家通过本关。
那么显然机器人的攻击次数是决定能否最快通关这款游戏的关键。小 D 现在得知了每条巨龙的所有属性,她想考考你,你知道应该将机器人的攻击次数xxx 设置为多少,才能用最少的攻击次数通关游戏吗?
当然如果无论设置成多少都无法通关游戏,输出−1-1−1 即可。
输入输出格式
输入格式:
从文件dragon.in 中读入数据。
第一行一个整数T ,代表数据组数。
接下来T 组数据,每组数据包含555 行。
-
每组数据的第一行包含两个整数,nnn 和mmm ,代表巨龙的数量和初始剑的数量;
-
接下来一行包含nnn 个正整数,第iii 个数表示第iii 条巨龙的初始生命值aia_iai ;
-
接下来一行包含nnn 个正整数,第iii 个数表示第iii 条巨龙的恢复能力pip_ipi ;
-
接下来一行包含nnn 个正整数,第iii 个数表示杀死第iii 条巨龙后奖励的剑的攻击力;
-
接下来一行包含mmm 个正整数,表示初始拥有的mmm 把剑的攻击力。
输出格式:
输出到文件dragon.out 中。 一共TTT 行。
第iii 行一个整数,表示对于第iii 组数据,能够使得机器人通关游戏的最小攻击次数xxx ,如果答案不存在,输出−1-1−1。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
拓中,带系数的拓中。
将每个式子化成 x ≡ a (mod p) 的形式,然后拓中直接求。
代码:
#include<cstdio> #include<algorithm> using namespace std; #define ll long long #define inf 10000000000001ll #define N 200050 inline ll rd() { ll f=1,c=0;char ch = getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=(c<<3)+(c<<1)+ch-'0';ch=getchar();} return f*c; } ll T,n,m; struct sword { int ch[N][2],fa[N],rt,tot,rep[N]; ll w[N]; void rotate(int x) { int y = fa[x],z = fa[y],k = (ch[y][1]==x); ch[y][k] = ch[x][!k],fa[ch[x][!k]]=y; ch[x][!k] = y,fa[y] = x; ch[z][ch[z][1]==y] = x,fa[x] = z; } void splay(int x,int goal) { while(fa[x]!=goal) { int y = fa[x],z = fa[y]; if(z!=goal) ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y); rotate(x); } if(!goal)rt=x; } int findr(ll x) { int ret = rt,u = rt; while(u){if(w[u]>x)ret=u;u=ch[u][w[u]<=x];} splay(ret,0); return ret; } int findl(ll x) { int ret = rt,u = rt; while(u){if(w[u]<x)ret=u;u=ch[u][w[u]<x];} splay(ret,0); return ret; } ll find(ll x) { int ret = rt,u = rt; while(u){if(w[u]<x)ret=u;if(w[u]==x)return x;u=ch[u][w[u]<x];} splay(ret,0); return w[ret]; } void insert(ll k) { int u = rt,f=rt; while(u&&w[f]!=k)f=u,u=ch[u][w[u]<k]; if(w[f]==k) { rep[f]++; return ; } u=++tot; if(f)ch[f][k>w[f]]=u; fa[u]=f,rep[u]=1,w[u]=k; ch[u][0]=ch[u][1]=0; splay(u,0); } void erase(ll k) { int r = findr(k),l = findl(k); splay(l,0);splay(r,l); if(rep[ch[r][0]]>1) { rep[ch[r][0]]--; }else fa[ch[r][0]]=0,ch[r][0]=0; } void clear() { rt=tot=0; } }sw; ll ai[N],pi[N],wi[N],mx; void init() { sw.clear(); sw.insert(inf); sw.insert(-1); mx=-1; } ll exgcd(ll a,ll b,ll &x,ll &y) { if(!b) { x=1,y=0; return a; } ll ret = exgcd(b,a%b,y,x); y-=a/b*x; return ret; } ll mul(ll x,ll y,ll mod) { ll ret = 0; while(y) { if(y&1)ret=(ret+x)%mod; x=(x+x)%mod; y>>=1; } return ret; } ll zhx[N],jdr[N]; int fkzhx() { ll x,y,wk; for(int i=1;i<=n;i++) { wk = sw.find(ai[i]);if(wk<0)wk=sw.w[sw.findr(ai[i])];sw.erase(wk);sw.insert(wi[i]); ll gcd = exgcd(wk,pi[i],x,y); if(ai[i]%gcd)return 0; jdr[i] = pi[i]/gcd; x = mul(x,ai[i]/gcd,jdr[i]); x = (x%jdr[i]+jdr[i])%jdr[i]; zhx[i] = x; mx=max(mx,ai[i]/wk); } return 1; } ll excrt() { ll A = 0,P = 1,x,y; for(int i=1;i<=n;i++) { ll a = P , b = jdr[i] , c = ((zhx[i]-A)%b+b)%b;//取模,不然会死 ll gcd = exgcd(a,b,x,y); if(c%gcd)return -1; P *= jdr[i]/gcd; x = (x%P+P)%P,c = (c%P+P)%P; x = mul(x,c,P); A = (A + mul(P/jdr[i],x,P))%P; } A = (A%P+P)%P; if(A<mx)return A+((mx-A)/P+(mx%A!=0))*P;//不加特判会挂 return A; } int main() { T = rd(); while(T--) { init(); n=rd(),m=rd(); for(int i=1;i<=n;i++) ai[i]=rd(); for(int i=1;i<=n;i++) pi[i]=rd(); for(int i=1;i<=n;i++) wi[i]=rd(); for(int i=1;i<=m;i++) sw.insert(rd()); int fk = 1; for(int i=1;i<=n&&fk;i++) if(pi[i]!=1) fk=0; if(fk) { ll ans = 0,wk; for(int i=1;i<=n;i++) { wk = sw.find(ai[i]);if(wk<0)wk=sw.w[sw.findr(ai[i])];sw.erase(wk);sw.insert(wi[i]); ans = max(ans,ai[i]/wk+(ai[i]%wk!=0)); } printf("%lld\n",ans); }else { int r = fkzhx(); if(!r)printf("-1\n"); else printf("%lld\n",excrt()); } } return 0; }