π§© AtCoder Beginner Contest 382
π§© AtCoder Beginner Contest 382
# Info & Summary
- Date:
2024-12-30
- Completion Status: A β / B β / C β / D β / E β / F β / G β
- Problem Type:
Problem | Type(s) | Data Structure / Algo | π₯ Key Insight / Mark |
---|---|---|---|
D | Constructive | DFS | βπ₯ |
E | DP | Expectation DP | π§ π |
Details
Emoji | Label | Meaning |
---|---|---|
β | Important | Problem is strategically useful or has reusable patterns |
π₯ | Must master | Classic problem or technique that appears often and is worth mastering |
β οΈ | Reattempt | You attempted but failed; worth reviewing and solving again |
π§ | New to me | Introduced a new idea, technique, or pattern you hadnβt seen before |
π οΈ | Template | You built or improved a code template from solving this problem |
π | Too hard now | Beyond current ability to understand/solve; revisit after more practice |
π A - Daily Cookie

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n, d;
cin >> n >> d;
string s;
cin >> s;
int num = 0;
for (auto c : s)
{
num += c == '@';
}
cout << (n - num) + min(num, d) << endl;
return 0;
}
π B - Daily Cookie 2

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, D;
string S;
cin >> N >> D >> S;
for (int i = N - 1; i >= 0 && D > 0; i--)
{
if (S[i] == '@')
{
S[i] = '.';
D--;
}
}
cout << S << endl;
return 0;
}
π C - Kaiten Sushi

#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<int> A(N);
for (int i = 0; i < N; i++)
{
cin >> A[i];
}
vector<pair<int, int>> B(M);
for (int i = 0; i < M; i++)
{
int b;
cin >> b;
B[i] = {b, i};
}
sort(B.rbegin(), B.rend());
vector<int> ans(M, -1);
int i = 0, j = 0;
while (i < N && j < M)
{
while (j < M && B[j].first >= A[i])
{
ans[B[j].second] = i + 1;
j++;
}
i++;
}
for (int i = 0; i < M; i++)
{
cout << ans[i] << endl;
}
return 0;
}
π D - Keep Distance

Tips
A sequence of length is good if and only if
if , then will exceed even if it is at its minimum
Tips
Suppose that , and that is good sequence
Then, the range of such that is a good sequence if and only if
The problem can be solved by enumerating the good sequence according to this rule
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, M;
cin >> N >> M;
vector<vector<int>> ans;
auto dfs = [&](auto &&self, vector<int> v) -> void {
int sz = v.size();
if (sz == N)
{
ans.push_back(v);
return ;
}
for (int cur = (sz == 0 ? 1 : v.back() + 10); cur <= M - 10 * (N - sz - 1); cur++)
{
vector<int> nxt = v;
nxt.push_back(cur);
self(self, nxt);
}
};
dfs(dfs, {});
int cnt = ans.size();
cout << cnt << endl;
for (int i = 0; i < cnt; i++)
{
for (int j = 0; j < N; j++)
{
cout << ans[i][j] << " \n"[j == N - 1];
}
}
return 0;
}
π E - Expansion Packs

Tips
Let:
- : the expected number of packs we need to open to get exactly more rare cards
- : the probability that a pack contains exactly rare cards
The sought value is , the expected number of packs to collect rare cards
Tips
We evaluate in the manner of DP:
- For , we have
- For , considering the number of rare cards contained in the next pack to open, we can derive
But, this formula contains on both sides (in term), so we isolate it:
which enables us to find in ascending order of , since all right-hand terms are from earlier states
Therefore, when we know the values , we can compute in a total of time
Tips
Let : the probability that exactly rare cards appear in the first cards in a pack
By summing up the two cases where the -th card is and is not a rare card, we arrive at:
We initialize:
This DP runs in a total of time, and
Note
Time Complexity:
- Computing :
- Computing :
Total:
bottom-up DP
// Step 2: Compute f[i]: expected packs needed to collect i rare cards
vector<double> f(X + 1, 0.0);
for (int i = 1; i <= X; i++)
{
double sum = 1.0;
for (int j = 1; j <= N; j++)
{
// \sum_{j = 1}^{N}f_{\max(i - j, 0)} \times g_j
sum += f[max(0, i - j)] * g[j];
}
// f_i
f[i] = sum / (1.0 - g[0]);
}
// DP + memoization
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, X;
cin >> N >> X;
vector<int> P(N);
for (int i = 0; i < N; i++)
{
cin >> P[i];
}
// Step 1: compute g_j
vector<double> g(N + 1, 0.0);
vector<vector<double>> dp(N + 1, vector<double>(N + 1, 0.0));
dp[0][0] = 1.0;
for (int i = 1; i <= N; i++)
{
double p = P[i - 1] / 100.0;
for (int j = 0; j <= i; j++)
{
// if i-th card is not a rare card
dp[i][j] += dp[i - 1][j] * (1.0 - p);
// if i-th card is a rare card
if (j > 0)
{
dp[i][j] += dp[i - 1][j - 1] * p;
}
}
}
for (int j = 0; j <= N; j++)
{
g[j] = dp[N][j];
}
// Step 2: compute f_X
vector<double> memo_f(X + 1, -1.0);
auto calc_f = [&](auto &&self, int i) -> double
{
if (i <= 0)
{
return 0.0;
}
if (memo_f[i] >= 0.0)
{
return memo_f[i];
}
// 1 + \sum_{j = 1}^{N}f_{\max(i - j, 0)} \times g_j
double sum = 0.0;
sum += 1.0;
for (int j = 1; j <= N; j++)
{
sum += self(self, max(i - j, 0)) * g[j];
}
// f_i
memo_f[i] = sum / (1.0 - g[0]);
return memo_f[i];
};
double ans = calc_f(calc_f, X);
cout << fixed << setprecision(16) << ans << endl;
return 0;
}
π F - Falling Bars

Warning
Hard Problems to Tackle Later
// TODO
π G - Tile Distance 3

Warning
Hard Problems to Tackle Later
// TODO