• [补题记录] Atcoder Beginner Contest 323(E、F)


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

    目录

    E

    Problem/题意

    Thought/思路

    Code/代码

    F

    Problem/题意

     Thought/思路

    Code/代码


    E

    Problem/题意

    有 N 首歌曲,每首歌曲时长为 Ti。每次随机播放一首歌曲,问在 X + 0.5 这一时刻,播放第一首歌的概率是多少。

    Thought/思路

    如果我们能求出从 X - T[1] + 1 到 X 的每一时刻开始时,恰好播放完上一首歌的概率,那么就可以将这 T[1] 个时刻加起来,再除以 N,就是从 X 开始,播放第一首歌的概率。

    因此,dp[i] 表示,第 i 秒开始时,上一首歌结束,下一首歌准备开始播放的概率。

    当 i > T[j] 时,就可以把当前第 j 首歌播放的概率累加到 dp[i] 上。

    Code/代码

    1. #include "bits/stdc++.h"
    2. #define int long long
    3. const int mod = 998244353;
    4. int n, x, t[10007], dp[10007];
    5. int ksm(int a, int b) {
    6. int res = 1;
    7. while (b > 0) {
    8. if (b & 1) res = res * a % mod;
    9. a = a * a % mod;
    10. b >>= 1;
    11. }
    12. return res;
    13. }
    14. signed main() {
    15. std::cin >> n >> x;
    16. for (int i = 1; i <= n; ++ i) std::cin >> t[i];
    17. dp[0] = 1;
    18. for (int i = 1; i <= x; ++ i) {
    19. int cnt = 0;
    20. for (int j = 1; j <= n; ++ j) {
    21. if (i >= t[j]) {
    22. cnt ++;
    23. dp[i] = (dp[i] + ksm(n, mod - 2) * dp[i - t[j]] % mod) % mod;
    24. }
    25. }
    26. }
    27. int s = (x - t[1] + 1 < 0 ? 0 : x - t[1] + 1); // 从 s 开始放
    28. int ans = 0;
    29. for (int i = s; i <= x; ++ i) {
    30. ans = (ans + dp[i]) % mod;
    31. }
    32. ans = ans * ksm(n, mod - 2) % mod;
    33. std::cout << ans;
    34. }

    F

    Problem/题意

    给出三个点的坐标,点 A 表示人、点 B 表示一个箱子、点 C 表示目标点,现在要将箱子推到目标点:

    • 可以将箱子向上、下、左、右推,但人和箱子必须同一朝向且人在箱子之后;
    • 每走一格代价 + 1;
    • 问最小的代价是多少;

     Thought/思路

    From:https://zhuanlan.zhihu.com/p/660042738

    对于第二句话,我们可以将目标点 C 都换到上半轴,那么 A 只需要移动到 (0, -1)、(-1, 0)、(1, 0) 即可去到推箱子的最佳位置。

    详见代码。

    Code/代码

    1. #include "bits/stdc++.h"
    2. #define int long long
    3. struct node {
    4. int x, y;
    5. node operator - (const node &t) const {
    6. return node({x - t.x, y - t.y});
    7. }
    8. }a, b, c;
    9. void reverseAC() {
    10. c.x = -c.x;
    11. c.y = -c.y;
    12. a.x = -a.x;
    13. a.y = -a.y;
    14. }
    15. signed main() {
    16. std::cin >> a.x >> a.y;
    17. std::cin >> b.x >> b.y;
    18. std::cin >> c.x >> c.y;
    19. // 以 b 为中心
    20. a.x -= b.x;
    21. a.y -= b.y;
    22. c.x -= b.x;
    23. c.y -= b.y;
    24. b.x = b.y = 0;
    25. int ans = std::abs(c.x) + std::abs(c.y); // 先算 B 到 C 的代价
    26. if (c.x < 0 and c.y < 0) { // 将 C 偏移到右上方
    27. reverseAC();
    28. }
    29. if (c.x > 0 and c.y > 0) { // A 移动到 -1, 0 或 0, -1
    30. node p1 = a - node({-1, 0}), p2 = a - node({0, -1});
    31. // +2 是因为移动箱子时,需要换方向
    32. ans += std::min(std::abs(p1.x) + std::abs(p1.y), std::abs(p2.x) + std::abs(p2.y)) + 2;
    33. std::cout << ans;
    34. return 0;
    35. }
    36. if (c.x > 0 and c.y < 0) {
    37. reverseAC();
    38. }
    39. if (c.x < 0 and c.y > 0) {
    40. node p1 = a - node({1, 0}), p2 = a - node({0, -1});
    41. ans += std::min(std::abs(p1.x) + std::abs(p1.y), std::abs(p2.x) + std::abs(p2.y)) + 2;
    42. std::cout << ans;
    43. return 0;
    44. }
    45. if (c.x == 0) { // C 在轴上
    46. if (c.y < 0) { // 将 C 偏移到正半轴
    47. reverseAC();
    48. }
    49. if (a.x == 0 and a.y > 0) { // A 也在正半轴上,需要绕回负半轴
    50. ans += 2;
    51. }
    52. node p = a - node({0, -1});
    53. ans += std::abs(p.x) + std::abs(p.y);
    54. std::cout << ans;
    55. return 0;
    56. }
    57. if (c.y == 0) {
    58. if (c.x < 0) {
    59. reverseAC();
    60. }
    61. if (a.y == 0 and a.x > 0) {
    62. ans += 2;
    63. }
    64. node p = a - node({-1, 0});
    65. ans += std::abs(p.x) + std::abs(p.y);
    66. std::cout << ans;
    67. return 0;
    68. }
    69. }

  • 相关阅读:
    ubuntu 20.04 docker 安装 mysql
    Element-plus 图标使用
    设计模式-工厂设计模式
    中断系统中的设备树__中断号的演变与irq_domain
    TwinCAT3添加伺服控制器的方法
    【TB作品】基于MSP430G2553单片机的超声波测距与报警系统,原理图,PCB
    C++ 中的虚函数和多态性
    linux下提示:pip未找到命令(bash: pip: command not found)
    Revit插件“土建模块”的生成圈梁功能使用
    LeetCode【279】完全平方数
  • 原文地址:https://blog.csdn.net/joyride_run/article/details/133687301