URL:https://atcoder.jp/contests/abc323

目录
有 N 首歌曲,每首歌曲时长为 Ti。每次随机播放一首歌曲,问在 X + 0.5 这一时刻,播放第一首歌的概率是多少。
如果我们能求出从 X - T[1] + 1 到 X 的每一时刻开始时,恰好播放完上一首歌的概率,那么就可以将这 T[1] 个时刻加起来,再除以 N,就是从 X 开始,播放第一首歌的概率。
因此,dp[i] 表示,第 i 秒开始时,上一首歌结束,下一首歌准备开始播放的概率。
当 i > T[j] 时,就可以把当前第 j 首歌播放的概率累加到 dp[i] 上。
- #include "bits/stdc++.h"
-
- #define int long long
-
- const int mod = 998244353;
-
- int n, x, t[10007], dp[10007];
-
- int ksm(int a, int b) {
- int res = 1;
- while (b > 0) {
- if (b & 1) res = res * a % mod;
- a = a * a % mod;
- b >>= 1;
- }
- return res;
- }
-
- signed main() {
- std::cin >> n >> x;
- for (int i = 1; i <= n; ++ i) std::cin >> t[i];
-
- dp[0] = 1;
- for (int i = 1; i <= x; ++ i) {
- int cnt = 0;
- for (int j = 1; j <= n; ++ j) {
- if (i >= t[j]) {
- cnt ++;
- dp[i] = (dp[i] + ksm(n, mod - 2) * dp[i - t[j]] % mod) % mod;
- }
- }
- }
-
- int s = (x - t[1] + 1 < 0 ? 0 : x - t[1] + 1); // 从 s 开始放
- int ans = 0;
- for (int i = s; i <= x; ++ i) {
- ans = (ans + dp[i]) % mod;
- }
- ans = ans * ksm(n, mod - 2) % mod;
-
- std::cout << ans;
- }
给出三个点的坐标,点 A 表示人、点 B 表示一个箱子、点 C 表示目标点,现在要将箱子推到目标点:
From:https://zhuanlan.zhihu.com/p/660042738

对于第二句话,我们可以将目标点 C 都换到上半轴,那么 A 只需要移动到 (0, -1)、(-1, 0)、(1, 0) 即可去到推箱子的最佳位置。
详见代码。
- #include "bits/stdc++.h"
-
- #define int long long
-
- struct node {
- int x, y;
- node operator - (const node &t) const {
- return node({x - t.x, y - t.y});
- }
- }a, b, c;
-
- void reverseAC() {
- c.x = -c.x;
- c.y = -c.y;
- a.x = -a.x;
- a.y = -a.y;
- }
-
- signed main() {
- std::cin >> a.x >> a.y;
- std::cin >> b.x >> b.y;
- std::cin >> c.x >> c.y;
-
- // 以 b 为中心
- a.x -= b.x;
- a.y -= b.y;
- c.x -= b.x;
- c.y -= b.y;
- b.x = b.y = 0;
-
- int ans = std::abs(c.x) + std::abs(c.y); // 先算 B 到 C 的代价
-
- if (c.x < 0 and c.y < 0) { // 将 C 偏移到右上方
- reverseAC();
- }
- if (c.x > 0 and c.y > 0) { // A 移动到 -1, 0 或 0, -1
- node p1 = a - node({-1, 0}), p2 = a - node({0, -1});
- // +2 是因为移动箱子时,需要换方向
- ans += std::min(std::abs(p1.x) + std::abs(p1.y), std::abs(p2.x) + std::abs(p2.y)) + 2;
- std::cout << ans;
- return 0;
- }
-
- if (c.x > 0 and c.y < 0) {
- reverseAC();
- }
- if (c.x < 0 and c.y > 0) {
- node p1 = a - node({1, 0}), p2 = a - node({0, -1});
- ans += std::min(std::abs(p1.x) + std::abs(p1.y), std::abs(p2.x) + std::abs(p2.y)) + 2;
- std::cout << ans;
- return 0;
- }
-
- if (c.x == 0) { // C 在轴上
- if (c.y < 0) { // 将 C 偏移到正半轴
- reverseAC();
- }
- if (a.x == 0 and a.y > 0) { // A 也在正半轴上,需要绕回负半轴
- ans += 2;
- }
- node p = a - node({0, -1});
- ans += std::abs(p.x) + std::abs(p.y);
- std::cout << ans;
- return 0;
- }
- if (c.y == 0) {
- if (c.x < 0) {
- reverseAC();
- }
- if (a.y == 0 and a.x > 0) {
- ans += 2;
- }
- node p = a - node({-1, 0});
- ans += std::abs(p.x) + std::abs(p.y);
- std::cout << ans;
- return 0;
- }
- }