题解链接:题解链接
RD是输入,OT是输出
A – SERVAL VS MONSTER
链接:
A题
题意:
给你怪物血量H和攻击一次扣A血,问至少要攻击几次能使怪物的血量小于或者等于0
解法:
按题意模拟,考虑到循环减去时间会较长,故判断奇偶后除求解攻击次数
代码
int main(){
LL h, a;
RD(h, a);
if (h%a == 0) cout << h/a << '\n';
else cout << h/a+1 << '\n';
}
B – COMMON RACCOON VS MONSTER
链接:
B题
题意:
怪物有H滴血,有N种攻击方式,每种攻击方式能造成ai的伤害,问每种攻击方式攻击一次是否能够使怪物血量小于或者等于0
解法:
模拟,直接扣最后判断即可
代码:
int main(){
int h, n; RD(h, n);
for(int i = 0; i < n; i++){
LL x; RD(x);
h-=x;
}
if (h <= 0) OT("Yes\n");
else OT("No\n");
}
C – FENNEC VS MONSTER
链接:
c题
题意:
Fennec 和 N 个怪物进行战斗,第 i 个怪物的血量为 Hi ,Fennec可以进行两种操作,一种攻击扣一滴血,另一种特殊攻击,能够使一个怪物的血量降到0,但是特殊攻击只能进行K次,求需要进行几次攻击
解法:
删去K个H大的怪物,剩余的平a
代码:
const int N = 2e5+50;
int H[N];
int main(){
LL n, k; RD(n, k);
REP(i, n) RD(H[i]);
sort(H, H+n);
LL ans = 0;
for(int i = 0; i < n-k; i++){
ans += H[i];
}
OT(ans);
}
D – CARACAL VS MONSTER
链接:
D题
题意:
怪物有H滴血,有两种操作方式,问需要操作几次?
如果 H > 1进行分裂和扣半血操作(扣半血是下取整操作)【这是算一次操作】
如果 H <= 1直接血量降为 0
解法:
仔细看样例会知道这是一题数学题,多列样例猜测规律
血量H 操作次数ans
1 1
2 3
3 3
4 7
…
1000000000000 1099511627775
画出图来后知道在大于1的时候一定要经过分裂,直到分裂扣血到1停止
int main(){
LL h; RD(h);
LL ans = 0, x = 1;
while(x <= h){ans+=x;x<<=1;}
OT(ans);
}
E – CRESTED IBIS VS MONSTER
类型:
完全背包问题、动态规划
链接:
E题
题意:
怪物有H滴血,魔法师有N个技能,每进行i技能时,魔法师自身消耗b[ i ]法力值,怪物扣血a[ i ],求使怪物血量小于等于0,最少消耗的法力值
解法:
H滴血相当于背包容量,N个技能相当于N种选择,a[ i ] 相当于物品重量, b[ i ]相当于每个物品的价值
转移方程
int x = max(0, j-a[i]);
dp[j] = min(dp[j],dp[x]+b[i]);
即选择下一个技能的话就要加上下一个技能的b[ i ],不选择的话就不加
代码:
const int maxn = 1e5+10;
int a[maxn], b[maxn];
const int N = 1e4+10;
int dp[N]= {0};
int main(){
int h, n; RD(h, n);
for(int i = 1; i <= n; i++){
RD(a[i], b[i]);
}
FOR_1(i, 1, h) dp[i] = 1e9; dp[0] = 0;
FOR_1(i, 1, n){
FOR_1(j, 0, h){
int x = max(0, j-a[i]);
dp[j] = min(dp[j],dp[x]+b[i]);
}
}
OT(dp[h]);
}
F – SILVER FOX VS MONSTER
链接:
F题
题意:
银狐和N个怪物战斗。N个怪物在一条线上,第i个怪物站在第xi个位置,并且具有hi点血量,现在进行激光炮对x位置进行轰击,会对x-D 到 x+D范围内怪物造成伤害,求解轰击次数。
解法:
建立一个c[ i ]计算每个点位的炮击次数need,即c[ i ]+=need,计算最远的炮击位置c[i+1] += c[i],超出范围的都会扣除need,所以+c[i]-need就会抵消了
代码:
const int N = 2e5+50;
LL c[N];
struct mos{
int x;
int h;
} p[N];
bool cmp(mos a, mos b){
return a.x < b.x;
}
int main(){
int n, a, d; RD(n, d, a);
FOR_1(i, 1, n){
RD(p[i].x, p[i].h);
}
sort(p+1, p+n+1, cmp);
LL ans = 0;
for (int i = 1,j = 1; i <= n; i++)
{
while(j <= n && p[j].x <= p[i].x + 2*d)
++j;
LL need = max((p[i].h - c[i]*a + a - 1)/a, 0ll);
ans += need;
c[i] += need;
c[j] -= need;
c[i+1] += c[i];
}
cout << ans << endl;
}