首先开始打一个怪兽肯定一直打到死为止。那么打死他要求的次数可以二分出来(其实暴力也可以)。两只怪兽交换打的顺序会不会变好?
先打第一只怪兽:
\(num_1*sumatk+num_2*(sumatk-atk_1)\)先打第二只怪兽:
\(num_2*sumatk+num_1*(sumatk-atk_2)\)那么什么情况下先打第二只会更好呢?当然是上式大于下式:
\(num_1*sumatk+num_2*(sumatk-atk_1)>num_2*sumatk+num_1*(sumatk-atk_2)\)化简:
\(num_1*atk_2>num_2*atk_1\)当上式成立时需要交换。
插进优先队列里面一搞,又不会爆longlong。一波搞定。
#includeusing namespace std;typedef long long ll;inline int read() { int x=0; int f=0; char c; do { c=getchar(); if(c=='-') f=1; } while(c<'0'||c>'9'); do { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); } while(c>='0'&&c<='9'); return f?-x:x;}inline void _write(int x) { if(x>9) _write(x/10); putchar(x%10+'0');}inline void write(int x) { if(x<0) { putchar('-'); x=-x; } _write(x); putchar('\n');}void TestCase(int ti);int main() {#ifdef Yinku freopen("Yinku.in","r",stdin); //freopen("Yinku.out","w",stdout);#endif // Yinku int T=read(); for(int ti=1;ti<=T;ti++) TestCase(ti);}/*--- ---*/inline int s1(int x){ return ((x+1)*x)>>1;}struct Monster{ int hp; int atk; int num; inline void calc(){ int l=1,r=1000,m; while(1){ m=l+r>>1; if(m==l){ int s=s1(l); if(s>=hp){ num=l; return; } else{ num=r; return; } } int s=s1(m); if(s==hp){ num=m; return; } else if(s =m.atk*num); }}monster;priority_queue pq;void TestCase(int ti) { ll sumatk=0; int n=read(); for(int i=1;i<=n;i++){ monster.hp=read(); monster.atk=read(); sumatk+=monster.atk; monster.calc(); pq.push(monster); } ll sumdamage=0; while(!pq.empty()){ monster=pq.top(); pq.pop(); sumdamage+=sumatk*monster.num; sumatk-=monster.atk; } printf("Case #%d: %lld\n",ti,sumdamage);}