Educational Codeforces Round 122 (Rated for Div. 2)
C题
因为你有 k k k次操作机会,而又因为题目中告诉我们 ∑ k ≤ 2 × 1 0 5 \sum k\le 2\times10^5 ∑k≤2×105,所以可以枚举哪几次增加攻击力,剩下的增加血量。
假设当前枚举到 i i i,那么当前的攻击力就是 d c + i × w dc+i\times w dc+i×w,血量就是 h c + ( k − i ) × a hc+(k-i)\times a hc+(k−i)×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题
因为 a i a_i ai初始都是 1 1 1,所以我们想到预处理出来 f 1 i f1_i f1i表示 1 1 1变成 i i i所需的最小步数。那么 f 1 i + i j = min { f 1 i + 1 } f1_i+\frac ij=\text{min}\{f1_{i}+1\} f1i+ji=min{f1i+1}
那么对于每组数据, f 1 b i f1_{b_i} f1bi实际就相当于体积, c i c_i ci就是价值,然后就是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;
}