Educational Codeforces Round 122 (Rated for Div. 2)
C题
因为你有kkk次操作机会,而又因为题目中告诉我们∑k≤2×105\sum k\le 2\times10^5∑k≤2×105,所以可以枚举哪几次增加攻击力,剩下的增加血量。
假设当前枚举到iii,那么当前的攻击力就是dc+i×wdc+i\times wdc+i×w,血量就是hc+(k−i)×ahc+(k-i)\times ahc+(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题
因为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;
}