Educational Codeforces Round 122 (Rated for Div. 2)

文章讨论了在EducationalCodeforcesRound122中的两道编程竞赛题目。C题涉及利用有限的操作机会优化角色的攻击力和血量,以确保能击败怪物。关键在于枚举增加攻击力的次数,并计算角色和怪物的生存轮数。D题则是一个关于预处理和01背包的问题,需要找到将1变成给定数字所需最小步骤,并应用到01背包的动态规划解决方案上。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Educational Codeforces Round 122 (Rated for Div. 2)

C题

因为你有kkk次操作机会,而又因为题目中告诉我们∑k≤2×105\sum k\le 2\times10^5k2×105,所以可以枚举哪几次增加攻击力,剩下的增加血量。

假设当前枚举到iii,那么当前的攻击力就是dc+i×wdc+i\times wdc+i×w,血量就是hc+(k−i)×ahc+(k-i)\times ahc+(ki)×a

然后分别计算怪物打死角色需要多少轮,角色打死怪物需要多少轮。

需要注意的几点

  • long long!
  • 一开始我先算角色打死怪物需要多少轮,然后看角色是否被打死,但判断角色是否被打死的时候会爆unsigned long long,所以还是要把他们分别算出来。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
int T;
ull hC, hM, dC, dM, k, w, a;
int main() {
    scanf("%d", &T);
    while (T--) {
        cin >> hC >> dC >> hM >> dM >> k >> w >> a;
        bool ok = false;
        for (int i = 0; i <= k; ++i) {
            ull d = dC + i * w;
            ull h = hC + (k - i) * a;
            ull t = (hM + (d - 1)) / d;
            ull p = (h + (dM - 1)) / dM;
            // cout << d << ' ' << h << ' ' << t << ' ' << (t - 1) * dM << endl;
            if (p < t) continue;
            puts("YES");
            ok = true;
            break;
        }
        if (!ok) puts("NO");
    }
    return 0;
}

D题

因为aia_iai初始都是111,所以我们想到预处理出来f1if1_if1i表示111变成iii所需的最小步数。那么 f1i+ij=min{f1i+1}f1_i+\frac ij=\text{min}\{f1_{i}+1\}f1i+ji=min{f1i+1}

那么对于每组数据,f1bif1_{b_i}f1bi实际就相当于体积,cic_ici就是价值,然后就是01背包了。

#include<bits/stdc++.h>
using namespace std;
const int N = 1010, M = 100010;
int T;
int n, k;
int b[N], c[N];
int f1[N], f[M];
void init() {
    memset(f1, 0x3f, sizeof(f1));
	f1[1] = 0;
	for (int i = 1; i <= 1000; ++i) {
		for (int j = 1; j <= 1000; ++j) {
			int u = i * 1.0 / j;
			if (u + i <= 1000) f1[u + i] = min(f1[u + i], f1[i] + 1);
		}
	}
}
int main(){
	init();
	scanf("%d", &T);
	while(T--) {
		scanf("%d%d", &n, &k);
		k = min(k, 12 * n);
        memset(f, 0, sizeof(f));
		for (int i = 1; i <= n; ++i) {
            scanf("%d", &b[i]);
            b[i] = f1[b[i]];
        }
		for (int i = 1; i <= n; ++i) scanf("%d", &c[i]);
		for (int i = 1; i <= n; ++i)
			for (int j = k; j >= b[i]; --j)
                f[j] = max(f[j], f[j - b[i]] + c[i]);
		printf("%d\n", f[k]);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值