[BZOJ5224]毁灭

在这里插入图片描述

  • 菜的真实,今天打膜泥赛,想了半天只想到了 ( T n 2 ) (Tn^2) 的暴力做法,30分本来觉得还可以了,神仙直接 A A 了,自闭了。
  • 30分:我们发现 O r z Orz (膜法值)、 a t k atk (攻击力)、 d e f def (防御值)都是有枚举的范围的,而生命值没有。不过假如我们知道了前三个,生命值自然可以确定。枚举一个 O r z Orz ,再枚举一个 a t k atk ,那么我们就知道了攻击有多少次。假设 b o s s boss 攻击 t t 次,那么对于防御和生命的花费
    c o s t = d e f b + ( n d e f ) t c cost=def*b+(n-def)*t*c
    = d e f ( b t c ) + n t c =def(b-tc)+n*t*c
  • 即def的花费是线性的,那么显然 d e f def 只有取 0 0 和取 n n 两种情况。30分有了。
  • 继续深入思考,对于def取n的情况,显然我们只需要再购买1个 a t k atk 就好了。
  • 对于 d e f def 0 0 ,假如 O r z Orz 的代价小于 a t k atk ,那么一次性秒杀 b o s s boss 一定是最优的。当 O r z Orz 代价大于 a t k atk 时, O r z Orz 的作用在于适当选取让自己少挨一次锤,从而减少生命的花费。那么此时我们需要枚举一个攻击次数,对于相同的攻击次数来说,肯定是攻击力最小的最优。对于通过增加 O r z Orz 来减少一次挨打来减小代价,一定是同一攻击次数里攻击力最大的那一个。考虑攻击力更小一点的,因为 O r z Orz 代价比攻击力代价大,所以显然没有变的更优。所以可以数论分块,每次两种情况尝试更新最优值。复杂度 O ( T n ) O(T\sqrt{n})

C o d i n g Coding

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int t,n,m,a,b,c,d;
ll ans;
int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%d%d%d%d%d%d",&n,&m,&a,&b,&c,&d);
		ans=1e17;int l,r,t;
		for(ans=min(1LL*n*b+a,1LL*m*d),l=1,r;l<=m;l=r+1){
			t=m/l;r=m/t;ans=min(ans,min(1LL*t*n*c+1LL*(m-r*t)*d+1LL*a*r,1LL*(t+1)*n*c+1LL*a*l));
		}
		printf("%lld\n",ans);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_39759315/article/details/88997132