AtCoder Beginner Contest 046
A
题意:
给 \(3\) 个数字,出现了多少不同的数字。
set
B
题意:
有 \(N\) 个球排成一行,每个球都被染成 \(K\) 种颜色之一,但是相邻球不能同色。询问总的染色方案。
\(1 \leq N \leq 1000, 2 \leq K \leq 1000\)
保证给出的数据导致的答案不会超过 int 。
题解:
第一个球有 K 种染色方案,后面的每个球只需要和左边的球不同色,有 K - 1 种染色方案。
\(ans = K(N - 1)^{K - 1}\)
加点难度,考虑 \(N\) 个球排成一圈,每个球都被染成 \(K\) 种颜色之一,但是相邻球不能同色的方案数。
不妨设 \(K\) 种颜色对 \(N\) 个球的环形不相邻染色为 \(dp_n\) 。
-
\(N\) 个球被染成 \(K\) 种颜色,且 \(i \in [2, N]\) 满足 \(c_i \neq c_{i - 1}\) 的方案数为:\(g_N = N(N - 1)^{K - 1}\) 。
-
\(N\) 个球被染成 \(K\) 种颜色,且 \(i \in [2, N]\) 满足 \(c_i \neq c_{i - 1}\) ,\(c_n = c_{1}\) 的方案数为:\(h_N = N(N - 1)^{K - 1}\) 。
根据容斥:\(f_N = g_N - h_N = g_N - f_{N + 1} = N(N - 1)^{K - 1} - f_{N + 1}\) 。良序下 \(f_2 = K(K - 1)\) 。
递推的时间复杂度 \(O(N)\) 。
如果愿意,这个递推式可以进一步计算出通项公式。
C
题意:
有两个人被投票,当前的比率为 \(A_1 : B_1\) 。随时间递增的 \(N\) 次比率为 \(A_1 : B_1, A_2 : B_2 : \cdots A_N : B_N\) 。
询问最少有多少人给他们投票,投票的人只会增多,且不能收回他的投票。保证答案不会超过 long long 。
\(1 \leq N, A, B \leq 1000\) 。
题解:
考虑逐级满足。\(\forall i \in [1, N - 1]\) 。假设此时 \(A_i, B_I\) 最小为 \(x_i, y_i\) 。
考虑 \(i + 1\) 加入,\(x_i, y_i\) 只可能变大。于是 \(p = max(\lceil \frac{x_i}{A_{i + 1}} \rceil, \lceil \frac{y_i}{B_{i + 1}} \rceil)\) ,\(x_{i + 1} = p A_{i + 1}, y_{i + 1} = p B_{i + 1}\) 。
int N; std::cin >> N;
ll x = 0, y = 0;
for (int i = 1; i <= N; i++) {
int a, b; std::cin >> a >> b;
if (i == 1) x = a, y = b;
else {
ll p = std::max((x + a - 1) / a, (y + b - 1) / b);
x = p * a; y = p * b;
}
}
std::cout << x + y << "\n";
D
题意:
\(A\) 和 \(B\) 在进行石头剪刀布游戏。不同于寻常的石头剪刀布,这个游戏的附加规则是:
- 只允许出石头和布
- 所有轮次结束后,每个玩家出石头的次数大于等于出布的次数
游戏有 \(n\) 轮,\(A\) 有超能力可以预知 \(B\) 每轮的手势,询问 \(A\) 能得到的最大分数。 \(win\) 记 \(1\) 分,\(lose\) 记 \(-1\) 分, \(tie\) 记 \(0\) 分。
石头用 \(g\) 表示,布用 \(p\) 表示。会给出一个字符串 \(s\) 表示总共 \(|s|\) 轮, \(B\) 按顺序每一轮的手势。
题解:
首先 \(A\) 的分数不会是负数,因为 \(A\) 可以模仿 \(B\) 的手势。
先让 \(A\) 模仿 \(B\) 的手势。设有 \(cnt_g\) 个 \(g\) ,\(cnt_p\) 个 \(p\) 。
可以证明在某一轮 \(A\) 将 \(p\) 改成 \(g\) 并故意输掉是没意义的。
于是 \(A\) 可以将 \(\lfloor \frac{cnt_g - cnt_p}{2} \rfloor\) 个 \(g\) 改成 \(p\) ,这便是能获得的分数。
std::string s; std::cin >> s;
std::string t = s;
int cnt_g = 0, cnt_p = 0;
for (int i = 0; i < t.size(); i++) {
cnt_g += t[i] == 'g';
}
cnt_p = (int)t.size() - cnt_g;
std::cout << (cnt_g - cnt_p) / 2 << "\n";
浙公网安备 33010602011771号