題目大意:c++
分裂怪有1到n種等級,ide
第1級的分裂怪稱爲原子怪,它不會分裂,被擊殺時會產生a[1]點經驗;spa
而第k級的分裂怪死亡時則會分裂成a[k]個第k - 1級的分裂怪。code
一個體力能夠殺死一個怪物。blog
q個詢問,每次給定一個整體力值,求最多能得到多少經驗it
二分消滅的1級怪的個數,不斷向上合併,能達到n級怪就是可行的event
合併中應該向上取整class
假設 1個i級怪會分裂成3個i+1級怪,此時若i+1級怪消滅了5個,則至少應消滅2個i級怪基礎
如有連續不少級別的怪物只會分裂成1個怪物 那麼就會出現一條長鏈 cli
把這一整條長鏈合併成一個點 記錄下這個點離合並了多少個點就能夠計算體力值的耗費了
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define LL long long #define inc(i,j,k) for(int i=j;i<=k;i++) #define dec(i,j,k) for(int i=j;i>=k;i--) #define gcd(i,j) __gcd(i,j) #define mem(i,j) memset(i,j,sizeof(i)) const int N=1e5+5; const int mod=1e9+7; int n,q,tot; LL v[N],s[N]; bool check(LL m,LL w) { int sum=n; // 還須要消滅sum個級別的怪物才能得到經驗 inc(i,1,tot) { if(m==1) return (w-sum)>=0; // 在消滅低級怪M個的基礎上 // 此時必須消滅當前級別的m個怪物 // 剩餘體力還有w 到第n級還有sum個級別 sum-=v[i]; w-=m*v[i]; if(i<tot) m=m/s[i+1]+(m%s[i+1]==0 ? 0:1); // 向上取整 if(w<0) return 0; // 體力不夠 無解 } return 1; } int main() { scanf("%d%d",&n,&q); tot=1; v[tot]=1LL; scanf("%lld",&s[tot]); inc(i,2,n) { LL t; scanf("%lld",&t); if(t==1) v[tot]++; else v[++tot]=1, s[tot]=t; // 把只能分裂1個低級怪的怪物鏈合起來 } while(q--) { LL w; scanf("%lld",&w); LL L=0,R=(LL)1e9,ans=0; while(L<=R) { LL M=(L+R)>>1; if(check(M,w)) ans=M, L=M+1; else R=M-1; } // 二分一共能打倒的一級怪的個數 printf("%lld\n",ans*s[1]); } return 0; }