qidao123.com技术社区-IT企服评测·应用市场

标题: Codeforces Round 998 (Div. 3) [打印本页]

作者: 自由的羽毛    时间: 6 天前
标题: Codeforces Round 998 (Div. 3)
A. Fibonacciness

标题大意

给你四个数字abde,让你找到一个中间值c,问                                    a                         +                         b                         =                         c                              a + b = c                  a+b=c ,                                    b                         +                         c                         =                         d                              b + c = d                  b+c=d ,                                    c                         +                         d                         =                         e                              c + d = e                  c+d=e 最多能有几个式子创建
解题思绪

显然最多就六种情况,暴力枚举即可
代码实现

  1. for _ in range(int(input())):
  2.     a1, a2, a4, a5 = map(int, input().split())
  3.     t1 = a1 + a2
  4.     t2 = a5 - a4
  5.    
  6.     ans = [0, 0]
  7.    
  8.     ans[0] += a1 + a2 == t1
  9.     ans[0] += a2 + t1 == a4
  10.     ans[0] += t1 + a4 == a5
  11.    
  12.     ans[1] += a1 + a2 == t2
  13.     ans[1] += a2 + t2 == a4
  14.     ans[1] += t2 + a4 == a5
  15.    
  16.     print(max(ans))
复制代码
B. Farmer John’s Card Game

标题大意

给你一个n行m列的排列,请你给出一个长度为n的排列,使得这n行每次出一个数字,执行m次,能按序次出完这                                    n                         ∗                         m                              n*m                  n∗m 个数字
解题思绪

对于同一行来说,下一次要出的数字会和本次相差n,全部只必要看排序后相邻是否相差n即可,每一行最小的数字就是他们的初始序次
代码实现

  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3. int main() {
  4.     std::ios::sync_with_stdio(false);
  5.     std::cin.tie(0);
  6.     std::cout.tie(0);
  7.     int t;
  8.     std::cin >> t;
  9.     while (t--) {
  10.         int n, m, f = 1;
  11.         std::cin >> n >> m;
  12.         std::vector<int> ans(n + 1);
  13.         std::vector<std::vector<int>> v(n, std::vector<int>(m));
  14.         for (int i = 0; i < n; i++) {
  15.             for (int j = 0; j < m; j++) {
  16.                 std::cin >> v[i][j];
  17.             }
  18.             std::sort(v[i].begin(), v[i].end());
  19.             for (int j = 1; j < m; j++) {
  20.                 if (v[i][j] - v[i][j - 1] != n) {
  21.                     f = 0;
  22.                 }
  23.             }
  24.             ans[v[i][0]] = i + 1;
  25.         }
  26.         if (f) {
  27.             for (int i = 0; i < n; i++) {
  28.                 std::cout << ans[i] << " \n"[i == n - 1];
  29.             }
  30.         } else {
  31.             std::cout << "-1\n";
  32.         }
  33.     }
  34. }
复制代码
C. Game of Mathletes

标题大意

有n个数字(保证n是偶数),执行n/2次操纵,每次Alice先选一个数字a,Bob再选一个数字b,如果满足                                    a                         +                         b                         =                         k                              a + b = k                  a+b=k,则可以加一分。 Alice会最小化分数,Bob会最大化分数,二者都接纳最优计谋,问末了得分会是多少
解题思绪

由于是Alice先手,全部Bob每次总能找到一个数字与Alice挑选的数字匹配(如果存在可以匹配的数字),因此只必要计算有多少数对满足等式即可
代码实现

  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3. int main() {
  4.     std::ios::sync_with_stdio(false);
  5.     std::cin.tie(0);
  6.     std::cout.tie(0);
  7.     int t;
  8.     std::cin >> t;
  9.     while (t--) {
  10.         int n, k;
  11.         std::cin >> n >> k;
  12.         std::vector<int> f(n + 1);
  13.         for (int i = 0; i < n; i++) {
  14.             int x;
  15.             std::cin >> x;
  16.             f[x]++;
  17.         }
  18.         i64 ans = 0;
  19.         for (int i = std::max(1, k - n); i < std::min(n + 1, (k + 1) / 2); i++) {
  20.             int j = k - i;
  21.             if (j >= 1 && j <= n && j > i) {
  22.                 ans += std::min(f[i], f[j]);
  23.             }
  24.         }
  25.         if (k % 2 == 0) {
  26.             int mid = k / 2;
  27.             if (mid >= 1 && mid <= n) {
  28.                 ans += f[mid] / 2;
  29.             }
  30.         }
  31.         std::cout << ans << "\n";
  32.     }
  33. }
复制代码
D. Subtract Min Sort

标题大意

有n个数字,可以多次执行                                              a                            i                                  −                         m                         i                         n                         (                                   a                            i                                  ,                                   a                                       i                               −                               1                                            )                              a_i - min(a_i, a_{i - 1})                  ai​−min(ai​,ai−1​),                                             a                            i                                  −                         m                         i                         n                         (                                   a                                       i                               −                               1                                            ,                                   a                                       i                               −                               1                                            )                              a_i - min(a_{i - 1}, a_{i - 1})                  ai​−min(ai−1​,ai−1​),问末了能否让序列单调不递减
解题思绪

对于一个单调不递减的序列,显然不绝执行操纵之后除了末了一位都会变成0,因此只必要不绝的执行操纵,末了检查前n-1位是不是0即可
代码实现

  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3. int main() {
  4.     std::ios::sync_with_stdio(false);
  5.     std::cin.tie(0);
  6.     std::cout.tie(0);
  7.     int t;
  8.     std::cin >> t;
  9.     while (t--) {
  10.         int n, f = 0;
  11.         std::cin >> n;
  12.         std::vector<int> a(n);
  13.         for (int i = 0; i < n; i++) {
  14.             std::cin >> a[i];
  15.         }
  16.         for (int i = 1; i < n; i++) {
  17.             int minn = std::min(a[i - 1], a[i]);
  18.             a[i - 1] -= minn;
  19.             a[i] -= minn;
  20.         }
  21.         for (int i = 0; i < n - 1; i++) {
  22.             f += a[i];
  23.         }
  24.         if (f) {
  25.             std::cout << "NO\n";
  26.         } else {
  27.             std::cout << "YES\n";
  28.         }
  29.     }
  30. }
复制代码
E. Graph Composition

标题大意

给你两张图F和G,每次操纵可以在F中删或者加一条边,末了要求让F和G联通性相同,问最小操纵次数是多少
解题思绪

按照题意模拟,对F中联通但是G不联通的部门直接删边ans++,对F中不联通G中联通的部门加边,末了加上二者连通块数量即可
代码实现

  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3. class DSU {
  4.    public:
  5.     int cnt;
  6.     std::vector<int> fa, rank, siz;
  7.     DSU(int n) : cnt(n), fa(n + 1), rank(n + 1, 0), siz(n + 1, 1) {
  8.         for (int i = 1; i <= n; i++) {
  9.             fa[i] = i;
  10.         }
  11.     }
  12.     int find(int x) {
  13.         if (fa[x] != x) {
  14.             fa[x] = find(fa[x]);
  15.         }
  16.         return fa[x];
  17.     }
  18.     void merge(int x, int y) {
  19.         int X = find(x), Y = find(y);
  20.         if (X != Y) {
  21.             if (rank[X] >= rank[Y]) {
  22.                 fa[Y] = X;
  23.                 siz[X] += siz[Y];
  24.                 if (rank[X] == rank[Y]) {
  25.                     rank[X]++;
  26.                 }
  27.             } else {
  28.                 fa[X] = Y;
  29.                 siz[Y] += siz[X];
  30.             }
  31.             cnt--;
  32.         }
  33.     }
  34.     int size() {
  35.         return cnt;
  36.     }
  37.     int count(int x) {
  38.         return siz[find(x)];
  39.     }
  40. };
  41. int main() {
  42.     std::ios::sync_with_stdio(false);
  43.     std::cin.tie(0);
  44.     int t;
  45.     std::cin >> t;
  46.     while (t--) {
  47.         i64 n, m1, m2, ans = 0;
  48.         std::cin >> n >> m1 >> m2;
  49.         std::vector<std::pair<int, int>> F(m1);
  50.         for (int i = 0; i < m1; i++) {
  51.             std::cin >> F[i].first >> F[i].second;
  52.         }
  53.         DSU dsuG(n);
  54.         for (int i = 0; i < m2; i++) {
  55.             int u, v;
  56.             std::cin >> u >> v;
  57.             dsuG.merge(u, v);
  58.         }
  59.         DSU dsuF(n);
  60.         for (auto [u, v] : F) {
  61.             if (dsuG.find(u) != dsuG.find(v)) {
  62.                 ans++;
  63.             } else {
  64.                 dsuF.merge(u, v);
  65.             }
  66.         }
  67.         std::cout << ans + dsuF.size() - dsuG.size() << "\n";
  68.     }
  69. }
复制代码
F. Multiplicative Arrays

标题大意

给你两个数字nk,问有多少个长度不超过n且最大元素不超过k的数组满足累乘后的值为x,输出x=1~k时的方案数,对最方案数模998244353
解题思绪

1是一个很特殊的数字,他可以让长度增加而累乘的值不增加,首先考虑最大值是1的情况发现只有n种,再考虑最小值不为1的情况,可以发现末了数组长度不会特殊长,而对于有1的情况基于没有1的情况填充即可
代码实现

  1. #include <bits/stdc++.h>
  2. using i64 = long long;
  3. const int MOD = 998244353;
  4. i64 ksm(i64 a, i64 n) {
  5.     i64 res = 1;
  6.     a %= MOD;
  7.     while (n) {
  8.         if (n & 1) res = res * a % MOD;
  9.         a = a * a % MOD;
  10.         n >>= 1;
  11.     }
  12.     return res;
  13. }
  14. int main() {
  15.     std::ios::sync_with_stdio(false);
  16.     std::cin.tie(0);
  17.     std::cout.tie(0);
  18.     int t;
  19.     std::cin >> t;
  20.     while (t--) {
  21.         i64 k, n;
  22.         std::cin >> k >> n;
  23.         if (k == 1) {
  24.             std::cout << (n % MOD) << "\n";
  25.             continue;
  26.         }
  27.         i64 p2 = 0;
  28.         while ((1ll << (p2 + 1)) <= k) {
  29.             p2++;
  30.         }
  31.         // 当序列只有一个大于1的数字时
  32.         i64 C = ((n + 1) % MOD) * (n % MOD) % MOD;
  33.         C = C * ksm(2, MOD - 2) % MOD;
  34.         std::vector<i64> ans(k + 1), last(k + 1);
  35.         for (int i = 2; i <= k; i++) {  // 选取方案不包含1
  36.             last[i] = 1;
  37.         }
  38.         for (int i = 1; i <= k; i++) {
  39.             ans[i] = (ans[i] + last[i] * C) % MOD;
  40.         }
  41.         for (int len = 2; len <= std::min(p2, n); len++) {
  42.             // 先填入大于1的数字
  43.             std::vector<i64> now(k + 1);
  44.             for (int i = 2; i <= k; i++) {  // 填入一个新数字i
  45.                 for (int j = i; j <= k; j += i) {  // 更新乘积
  46.                     now[j] = (now[j] + last[j / i]) % MOD;
  47.                 }
  48.             }
  49.             // 剩下的长度用1填充
  50.             C = C * ((n + 1 - len) % MOD + MOD) % MOD;
  51.             C = C * ksm(len + 1, MOD - 2) % MOD;
  52.             for (int i = 1; i <= k; i++) {
  53.                 ans[i] = (ans[i] + now[i] * C) % MOD;
  54.             }
  55.             last = now;
  56.         }
  57.         ans[1] = n % MOD;
  58.         for (int i = 1; i <= k; i++) {
  59.             std::cout << ans[i] << " \n"[i == k];
  60.         }
  61.     }
  62. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 qidao123.com技术社区-IT企服评测·应用市场 (https://dis.qidao123.com/) Powered by Discuz! X3.4