Educational Codeforces Round 95 (Rated for Div. 2)
A. Buying Torches
题目大意
1 1 1根棍子能换 x x x根棍子, y y y根棍子能换一份煤, 1 1 1根棍子和 1 1 1份煤能组成一根火柴,初始时你只有一根棍子,问你最少最多少次交换可以获得 k k k根火柴
解题思路
根据题目意思,我们至少要有
k
k
k块煤,那么就需要
k
y
ky
ky根棍子,还需要另外的
k
k
k根棍子与其组成
k
k
k根火柴,设
a
a
a为用棍子换棍子的次数,
b
b
b表示用棍子换煤块的次数,则有:
a
(
x
−
1
)
+
1
≥
b
y
+
k
a(x - 1) + 1 \geq by + k
a(x−1)+1≥by+k
其中
b
=
k
b=k
b=k
AC代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--) {
ll x, y, k;
cin >> x >> y >> k;
cout << (k * y + k - 1 + (x - 2)) / (x - 1) + k << '\n';
}
return 0;
}
B. Negative Prefixes
题目大意
给你一个长度为 n n n的数组,固定其中某些数字不动,设 P i P_{i} Pi为长度为 i i i的前缀和,令 k k k为 P P P中 P j < 0 P_{j}<0 Pj<0最大的 j j j,问你该数组能形成的许多排列中 k k k最小的情况,输出该排列
解题思路
从后往前看,即 P n ≥ 0 , P n − 1 ≥ 0 . . . P k + 1 ≥ 0 , P k < 0 P_{n}\geq 0, P_{n-1}\geq 0\ ...\ P_{k+1}\geq 0,P_{k}< 0 Pn≥0,Pn−1≥0 ... Pk+1≥0,Pk<0,那么我们显然要把大的往前放才能使得 k k k最小
固定不能动的数字,对其余数字从大到小排列,该排列即为所求
AC代码
#include <bits/stdc++.h>
using namespace std;
struct Node {
int w, l;
}a[110];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--) {
int n;
cin >> n;
for(int i = 1; i <= n; ++i) cin >> a[i].w;
for(int i = 1; i <= n; ++i) cin >> a[i].l;
for(int i = 1; i < n; ++i) {
if(a[i].l == 1) continue;
for(int j = i + 1; j <= n; ++j) {
if(a[j].l == 1) continue;
if(a[i].w < a[j].w) swap(a[i],a[j]);
}
}
for(int i = 1; i <= n; ++i) cout << a[i].w << " ";
cout << '\n';
}
return 0;
}
C. Mortal Kombat Tower
题目大意
有一个由0和1构成的数组,你和你的朋友从下标1开始前进,你的朋友一起移动,一次只能运动一步或两步,你和你的朋友交替进行,问你的朋友最少要经过多少个1
解题思路
正解 d p dp dp,但是记忆化搜索也能通过,按照题目意思进行分类讨论就行了
AC代码
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int n, a[maxn], dp[maxn][2][3];
//当前位置,轮到谁,移动了几步
int dfs(int pos, int who, int num) {
if(pos > n) return 0;
int res = 0x3f3f3f3f;
if(dp[pos][who][num] != 0x3f3f3f3f) return dp[pos][who][num]; //已经搜过直接返回
if(who == 0) { //你的朋友
if(num >= 2) res = dfs(pos + 1, 1, 1);
else if(num > 0) {
res = min(dfs(pos + 1, 1, 1), dfs(pos + 1, 0, num + 1) + a[pos]);
}
else {
res = dfs(pos + 1, 0, num + 1) + a[pos];
}
}
else { //你
if(num >= 2) res = dfs(pos + 1, 0, 1) + a[pos];
else if(num > 0) {
res = min(dfs(pos + 1, 0, 1) + a[pos], dfs(pos + 1, 1, num + 1));
}
else {
res = dfs(pos + 1, 1, num + 1);
}
}
return dp[pos][who][num] = min(dp[pos][who][num], res);
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while(T--) {
cin >> n;
for(int i = 1; i <= n; ++i) {
cin >> a[i];
dp[i][0][0] = dp[i][1][0] = 0x3f3f3f3f;
dp[i][0][1] = dp[i][1][1] = 0x3f3f3f3f;
dp[i][0][2] = dp[i][1][2] = 0x3f3f3f3f;
}
cout << dfs(1, 0, 0) << '\n';
}
return 0;
}