<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Title

      AtCoder Beginner Contest 427(A~E)

      AtCoder Beginner Contest 427(A~E)

      寫在前面

      賽時 \(A — E\)

      \(A\) : 模擬

      \(B\) : 模擬,暴力,前綴和

      \(C\) : \(dfs\)/狀態壓縮,二分圖概念,思維

      \(D\) : 博弈論(\(P/N\)態)

      \(E\) : 思維,\(BFS\)

      A - ABC -> AC

      思路

      按題意模擬就好了

      代碼

      #include <bits/stdc++.h>
      #define endl '\n'
      // #define int long long
      
      
      void solve()
      {
          std::string s; std::cin >> s;
          int tar = s.size() / 2;
          for (int i = 0; i < (int)s.size(); i++)
          {
              if (i == tar) continue;
              std::cout << s[i];
          }
      }
      
      signed main()
      {
          std::ios::sync_with_stdio(false);
          std::cout.tie(nullptr); std::cin.tie(nullptr);
          int _t = 1;
          // std::cin >> _t;
          while(_t--) solve();
          return 0;
      }
      

      B - Sum of Digits Sequence

      思路

      \(n\)很小,暴力計算即可

      可以維護一個\(f\)數組的前綴和

      這個過程就是,對于第\(i\)個數,此時我們應該是已經知道了前\(i - 1\)個元素的\(f\)前綴和
      那么此時就可以這樣處理

      \[ A_i = pref_{i - 1} \]

      \[ pref_i = pref_{i - 1} + f[A_i] \]

      而至于\(f[A_i]\)我們暴力求解就好

      代碼

      #include <bits/stdc++.h>
      #define endl '\n'
      // #define int long long
      
      int f[110];
      int a[110];
      int pre[110];
      void solve()
      {
          f[0] = 1; f[1] = 1; f[2] = 2; f[3] = 4; f[4] = 8;
          a[0] = 1; a[1] = 1; a[2] = 2; a[3] = 4; a[4] = 8;
          int n = 0; std::cin >> n;
          if (n <= 4)
          {
              std::cout << a[n] << endl;
              return;
          }
          pre[0] = f[0];
          for (int i = 1; i <= 4; i++) pre[i] = pre[i - 1] + f[i];
          for (int i = 5; i <= n; i++)
          {
              a[i] = pre[i - 1];
              int tmp = a[i]; int val = 0;
              while(tmp)
              {
                  val += tmp % 10;
                  tmp /= 10;
              }
              f[i] = val;
              pre[i] = pre[i - 1] + f[i];
          }
          // std::cout << f[5] << endl;
          std::cout << a[n] << endl;
      }
      
      signed main()
      {
          std::ios::sync_with_stdio(false);
          std::cout.tie(nullptr); std::cin.tie(nullptr);
          int _t = 1;
          // std::cin >> _t;
          while(_t--) solve();
          return 0;
      }
      

      C - Bipartize

      思路

      首先怎么判斷二分圖 \(\rightarrow\) 染色法,但是我們這里是要對其操作使之變成二分圖,染色法似乎不行. 但是我們可以注意到\(N\)很小,我們可以以\(O(2^n)\)去枚舉二分圖左集合有哪些元素,剩下的放到右集合。

      那么分配完后如何操作使之成為二分圖呢,因為二分圖只有左右集合點之間的連邊,集合內部是不能連邊的,所以分別對左右集合內部枚舉點對,有邊就計數一次,然后每一次枚舉左右集合的點時我們就更新最小值即可

      這里實現可以\(dfs\),也可以狀態壓縮

      代碼

      #include <bits/stdc++.h>
      #define endl '\n'
      // #define int long long
      int n, m;
      int mat[20][20];
      int vis[20];
      int ans = INT_MAX;
      void dfs(int step)
      {
          if (step == n + 1)
          {
              std::vector<int> left, right;
              for (int i = 1; i <= n; i++)
              {
                  if (vis[i]) left.push_back(i);
                  if (!vis[i]) right.push_back(i);
              } 
              int tmp = 0;
              for (int i = 0; i < (int)left.size(); i++)
              {
                  for (int j = i + 1; j < (int)left.size(); j++)
                  {
                      if (mat[left[i]][left[j]]) tmp++;
                  }
              }
              for (int i = 0; i < (int)right.size(); i++)
              {
                  for (int j = i + 1; j < (int)right.size(); j++)
                  {
                      if (mat[right[i]][right[j]]) tmp++;
                  }
              }
              ans = std::min(ans, tmp);
              return;
          }
          vis[step] = 1;
          dfs(step + 1);
          vis[step] = 0;
          dfs(step + 1);
      }
      
      void solve()
      {
          std::cin >> n >> m;
          for (int i = 1; i <= m; i++)
          {
              int u, v; std::cin >> u >> v;
              mat[u][v] = mat[v][u] = 1;
          }
          dfs(1);
          std::cout << ans << endl;
      }
      
      signed main()
      {
          std::ios::sync_with_stdio(false);
          std::cout.tie(nullptr); std::cin.tie(nullptr);
          int _t = 1;
          // std::cin >> _t;
          while(_t--) solve();
          return 0;
      }
      

      D - The Simple Game

      思路

      對P、N態的理解

      • \(N\)態 (N-position): Next player winning position,即“下一個”玩家(輪到他/她行動的玩家)有必勝策略的位置。可以理解為“必勝態”。

      • \(P\)態 (P-position): Previous player winning position,即“上一個”玩家(剛剛行動完的那個玩家)有必勝策略的位置。對于當前玩家來說,這是一個無論怎么走,對方都有辦法贏的局面。可以理解為“必敗態”。

      • 無法移動的狀態為\(P\)

      • 可以移動到\(P\)的狀態為\(N\)

      • 只能移動到\(N\)的狀態為\(P\)

      這個題目我們代入Alice的視角去考慮
      我們考慮游戲結束時,也就是剩余步數為0時,當前落在A,就是必勝態(也就是N態); 當前落在B,就是必敗態(也就是P態)
      那么當游戲剩余1步時,此時該Bob走了,如果它能走到剩余0步時的P態,那此時Alice必敗,那么就是P態; 如果Bob不管怎么走都只能走到N態,那么Alice必勝,那么就是N
      \(\dots\)
      我們可以按照步數把圖分層做\(dp\)

      \(dp[i][j]\) : 剩余\(j\)步時,在節點\(i\)\(P\)\(N\)態,\(P\)態為\(1\), \(N態\)\(0\),那么最后我們判斷\(dp[1][2k]\)就好了

      \(j\)為奇數,也就是該Bob走時

      \[ dp[i][j] = \begin{cases} 0 & \exists v|i \space can \space go \space to \space v \space \space \ \ \ \ \ dp[v][j - 1] = 0\\ 1 & \forall v|i \space can \space go \space to \space v \space \space \ \ \ \ \ dp[v][j - 1] = 1 \end{cases} \]

      \(j\)為偶數時,也就是該Alice走時

      \[ dp[i][j] = \begin{cases} 1 & \exists v|i \space can \space go \space to \space v \space \space \ \ \ \ \ dp[v][j - 1] = 1\\ 0 & \forall v|i \space can \space go \space to \space v \space \space \ \ \ \ \ dp[v][j - 1] = 0 \end{cases} \]

      代碼

      #include <bits/stdc++.h>
      #define endl '\n'
      // #define int long long
      struct Edge
      {
          int u, v, nxt;
      };
      void solve()
      {
          int n = 0, m = 0, k = 0;
          std::cin >> n >> m >> k;
          std::vector<char> s(2 * n + 1);
          for (int i = 1; i <= n; i++) std::cin >> s[i];
          std::vector<Edge> g(2 * m + 1);
          std::vector<int> head(3 * n + 1, 0);
          int tot = 1;
          auto Add = [&](int u, int v) -> void
          {
              g[++tot] = {u, v, head[u]};
              head[u] = tot;
          };
          for (int i = 1; i <= m; i++)
          {
              int tu, tv; std::cin >> tu >> tv;
              Add(tu, tv);
          }
          std::vector<std::vector<int>> dp(n + 1, std::vector<int>(2 * k + 1, 0));
          for (int i = 1; i <= n; i++)
          {
              if (s[i] == 'A') dp[i][0] = 1;
          }
          for (int i = 1; i <= 2 * k; i++)
          {
              for (int i = 1; i <= 2 * k; i++)
              {
                  if (i % 2 != 0) 
                  {
                      for (int j = 1; j <= n; j++) 
                      {
                          bool ok = true;
                          for (int u = head[j]; u; u = g[u].nxt)
                          {
                              int v = g[u].v;
                              if (dp[v][i - 1] == 0) 
                              {
                                  ok = false;
                                  break;
                              }
                          }
                          if (ok) dp[j][i] = 1;
                      }
                  }
                  else 
                  {
                      for (int j = 1; j <= n; j++) 
                      {
                          bool ok = false;
                          for (int u = head[j]; u; u = g[u].nxt)
                          {
                              int v = g[u].v;
                              if (dp[v][i - 1] == 1) 
                              {
                                  ok = true;
                                  break;
                              }
                          }
                          if (ok) dp[j][i] = 1;
                      }
                  }
              }
          }
          if (dp[1][2 * k] == 1)
          {
              std::cout << "Alice" << endl;
          }
          else
          {
              std::cout << "Bob" << endl;
          }
      }
      
      signed main()
      {
          std::ios::sync_with_stdio(false);
          std::cout.tie(nullptr); std::cin.tie(nullptr);
          int _t = 1;
          std::cin >> _t;
          while(_t--) solve();
          return 0;
      }
      

      E - Wind Cleaning

      思路

      因為數據很小,我們可以把所有垃圾的位置視為一個狀態,但是有可能因為遍歷順序不同導致可能有相同的垃圾位置集合,最后的狀態表示不一樣,怎么辦呢? \(\rightarrow\) 排序,按照一個統一的標準來就好了

      接下來的流程就和\(bfs\)一樣了

      • 我們用一個隊列來記錄垃圾狀態移動的步數
      • 用一個set記錄有沒有訪問過一個狀態
      • 每次先從隊列中取出一個狀態,然后將這個狀態出隊,如果這個狀態已經遍歷過,\(continue\)掉繼續遍歷,記這個狀態為cur
      • 如果cur狀態已經合法,結束輸出答案
      • 因為所有垃圾都要移動,所以我們按照方向來遍歷,對每一個方向移動后的新狀態記為nxt
        • 檢查狀態合法性,不合法立即放棄這個方向
        • 如果有垃圾超出了邊界,不在加入后續狀態中
      • 隊列為空時還沒有找到答案就輸出-1

      代碼

      #include <bits/stdc++.h>
      #define endl '\n'
      // #define int long long
      const int dir[4][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
      std::vector<std::pair<int, int>> trash;
      std::queue<std::pair<std::vector<std::pair<int, int>>, int>> q;
      std::set<std::vector<std::pair<int, int>>> vis;
      int tx, ty;
      int h, w;
      
      void solve()
      {
          std::cin >> h >> w;
          for (int i = 1; i <= h; i++)
          {
              for (int j = 1; j <= w; j++)
              {
                  char tmp; std::cin >> tmp;
                  if (tmp == 'T') {tx = i; ty = j;}
                  if (tmp == '#') trash.push_back({i, j});
              }
          }
          std::sort(trash.begin(), trash.end());
          q.push({trash, 0});
          while(!q.empty())
          {
              auto [arr, dis] = q.front(); q.pop();
              if (vis.find(arr) != vis.end()) continue;
              if (arr.empty()) {std::cout << dis << endl; return;}
              vis.insert(arr);
              for (int i = 0; i < 4; i++)
              {
                  std::vector<std::pair<int, int>> nxt;
                  bool ok = true;
                  for (auto p : arr)
                  {
                      int nx = p.first + dir[i][0];
                      int ny = p.second + dir[i][1];
                      if (nx == tx && ny == ty)
                      {
                          ok = false;
                          break;
                      }
                      if (nx < 1 || nx > h || ny < 1 || ny > w) continue;
                      nxt.push_back({nx, ny});
                  }
                  if (ok == false) continue;
                  std::sort(nxt.begin(), nxt.end());
                  q.push({nxt, dis + 1});
              }
          }
          std::cout << -1 << endl;
      }
      
      signed main()
      {
          std::ios::sync_with_stdio(false);
          std::cout.tie(nullptr); std::cin.tie(nullptr);
          int _t = 1;
          // std::cin >> _t;
          while(_t--) solve();
          return 0;
      }
      
      posted @ 2025-10-12 10:40  栗悟飯與龜功気波  閱讀(31)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产超碰无码最新上传| 国产成人精品亚洲一区二区| 国产精品日韩中文字幕熟女| 97无码人妻福利免费公开在线视频| 最新国产精品好看的精品| 日本精品aⅴ一区二区三区| 久久九九精品国产免费看小说| 隆德县| 国产精一区二区黑人巨大| 开心五月激情综合久久爱| 人与禽交av在线播放| 亚洲AVAV天堂AV在线网阿V| 成人污视频| 伊人久久综合无码成人网| 久久精品国产福利一区二区| 日韩中文字幕在线不卡一区| 亚洲精品一区二区五月天| 亚洲精品一区国产精品| 国产区成人精品视频| 日韩一区二区三区一级片| 99久久国产综合精品女同| 欧美大胆老熟妇乱子伦视频| 国产日韩一区二区四季| 人妻少妇久久中文字幕一区二区| 高潮迭起av乳颜射后入| 网友自拍视频一区二区三区| 免费人成再在线观看视频| 熟女人妻精品一区二区视频| 国产目拍亚洲精品二区| 亚洲av无码牛牛影视在线二区 | 亚洲中文字幕无码爆乳| 精品国产一区av天美传媒| 艳妇乳肉豪妇荡乳av| 国产成人高清在线重口视频| 中国女人高潮hd| 酉阳| 国产精品乱码久久久久久小说| 四虎国产精品成人| 2021国产成人精品久久| 亚洲国产成人精品无色码| 欧美激情内射喷水高潮|