1. 程式人生 > >BZOJ5418:[NOI2018]屠龍勇士(exCRT,exgcd,set)

BZOJ5418:[NOI2018]屠龍勇士(exCRT,exgcd,set)

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

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\n",maxn); 74 else printf("%lld\n",exCRT()); 75 } 76 }