Description
Input
Output
Sample Input
2
3 3
3 5 7
4 6 10
7 3 9
1 9 1000
3 2
3 5 6
4 8 7
1 1 1
1 1
3 3
3 5 7
4 6 10
7 3 9
1 9 1000
3 2
3 5 6
4 8 7
1 1 1
1 1
Sample Output
59
-1
Solution
当时同步赛的时候写出来了……只不过忘了是爆$long~long$还是小细节写爆了只有$75$……
当时蠢的一比直接强上了一颗$splay$强行增加码量……现在觉得当时太蠢了然后就重写了一遍……
首先对于这个题,每次使用的剑可以发现是固定的,这个可以使用$set$来求出来。
知道了攻击力,知道了龙的血量和回血,就可以$exgcd$求出用多少刀的倍数砍死龙了。这其实是一个同余方程。
把所有同余方程搞出来,然后$exCRT$求解同余方程组就完事了QAQ
记得用快速乘还有特判一下回血全是$1$的情况。
Code
1 #include<iostream> 2 #include<cstdio> 3 #include<set> 4 #define N (100009) 5 #define LL long long 6 using namespace std; 7 8 LL T,n,m,x,a[N],p[N],v[N],Ai[N],Mod[N]; 9 multiset<LL>S; 10 11 LL Mul(LL a,LL b,LL MOD) 12 { 13 LL tmp=a*b-(LL)((long double)a*b/MOD+0.1)*MOD; 14 return tmp<0?tmp+MOD:tmp; 15 } 16 17 void exgcd(LL a,LL b,LL &d,LL &x,LL &y) 18 { 19 if (!b) {d=a; x=1; y=0; return;} 20 exgcd(b,a%b,d,y,x); y-=x*(a/b); 21 } 22 23 LL Find(LL x) 24 { 25 multiset<LL>::iterator it; 26 it=S.upper_bound(x); 27 if (it!=S.begin()) it--; 28 LL ans=*it; 29 S.erase(it); 30 return ans; 31 } 32 33 LL exCRT() 34 { 35 LL M=Mod[1],A=Ai[1],d,x,y,t; 36 for (int i=2; i<=n; ++i) 37 { 38 exgcd(M,Mod[i],d,x,y); 39 if ((Ai[i]-A)%d) return -1; 40 t=Mod[i]/d; x=(x%t+t)%t; x=Mul(x,(Ai[i]-A)/d,t); 41 A=M*x+A; M=M/d*Mod[i]; A%=M; 42 } 43 A=(A%M+M)%M; 44 return A; 45 } 46 47 int main() 48 { 49 scanf("%lld",&T); 50 while (T--) 51 { 52 S.clear(); 53 scanf("%lld%lld",&n,&m); 54 for (int i=1; i<=n; ++i) scanf("%lld",&a[i]); 55 for (int i=1; i<=n; ++i) scanf("%lld",&p[i]); 56 for (int i=1; i<=n; ++i) scanf("%lld",&v[i]); 57 for (int i=1; i<=m; ++i) scanf("%lld",&x), S.insert(x); 58 59 LL maxn=-1,flag=1,all_one=1; 60 for (int i=1; i<=n; ++i) 61 { 62 LL A=Find(a[i]),B=p[i],C=a[i],x,y,d; 63 exgcd(A,B,d,x,y); 64 if (C%d) {flag=0; break;} 65 x=(x%B+B)%B; 66 Ai[i]=Mul(x,C/d,B); Mod[i]=B/d; 67 if (p[i]!=1) all_one=0; 68 maxn=max(maxn,a[i]/A+(a[i]%A!=0)); 69 S.insert(v[i]); 70 } 71 72 if (!flag) {puts("-1"); continue;} 73 if (all_one) printf("%lld ",maxn); 74 else printf("%lld ",exCRT()); 75 } 76 }