既然补了就简单记录一下。

感觉还算有一点营养。

官方题解传送门:点我

Commentary Boxes

对拆掉$n \mod m$个和新建$m - (n \mod m)$求个最小。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long ll;
  6.  
  7. int main() {
  8. ll n, m, a, b, r;
  9. scanf("%lld%lld%lld%lld", &n, &m, &a, &b);
  10. r = n % m;
  11. printf("%lld\n", min(b * r, (m - r) * a));
  12. return ;
  13. }

A

Micro-World

对所有数排序,从小到大扫,能吃就吃。

一个细菌如果不被刚好比它大的那个吃掉,那么再大一点的也不能吃掉。

注意到相同的数可能处理起来有一点问题,像我这种懒人就直接开个$map$当平衡树用。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <map>
  4. using namespace std;
  5.  
  6. int n, k;
  7. map <int, int> mp;
  8.  
  9. template <typename T>
  10. inline void read(T &X) {
  11. X = ; char ch = ; T op = ;
  12. for (; ch > ''|| ch < ''; ch = getchar())
  13. if (ch == '-') op = -;
  14. for (; ch >= '' && ch <= ''; ch = getchar())
  15. X = (X << ) + (X << ) + ch - ;
  16. X *= op;
  17. }
  18.  
  19. int main() {
  20. read(n), read(k);
  21. for (int v, i = ; i <= n; i++) {
  22. read(v);
  23. ++mp[v];
  24. }
  25.  
  26. map <int, int> :: iterator lst = mp.begin(), now = mp.begin();
  27. ++now;
  28. int ans = ;
  29. for (; now != mp.end(); ++lst, ++now)
  30. if (now -> first <= lst -> first + k) ans += lst -> second;
  31.  
  32. printf("%d\n", n - ans);
  33. return ;
  34. }

B

Bracket Sequences Concatenation Problem

话说最近的几场中有类似的题目啊。

一个括号序列在自身匹配完之后一定能表示成若干个右括号$+$若干个左括号(比如$))))(((($)的形式,两个括号序列接起来能匹配的充要条件是:

1、前面的那个没有多余的右括号。

2、后面的那个没有多余的左括号。

3、前面的左括号和后面的右括号个数相同。

开个$map$正反扫一扫,注意不要忘记计算一个括号序列自身可能的贡献。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <map>
  4. #include <iostream>
  5. using namespace std;
  6. typedef pair <int, int> pin;
  7. typedef long long ll;
  8.  
  9. const int N = 3e5 + ;
  10.  
  11. int n;
  12. pin a[N];
  13. char s[N];
  14. map <int, int> mp;
  15.  
  16. int main() {
  17. scanf("%d", &n);
  18. for (int i = ; i <= n; i++) {
  19. scanf("%s", s + );
  20. int len = strlen(s + ), top = ;
  21. for (int j = ; j <= len; j++) {
  22. if (s[j] == '(') ++top;
  23. else {
  24. if (top) --top;
  25. else ++a[i].first;
  26. }
  27. }
  28. if (top != ) a[i].second += top;
  29. }
  30.  
  31. ll ans = ;
  32. for (int i = ; i <= n; i++) {
  33. if (a[i].second == ) ans += mp[a[i].first];
  34. if (a[i].first == ) ++mp[a[i].second];
  35. }
  36.  
  37. mp.clear();
  38. for (int i = n; i >= ; i--) {
  39. if (a[i].second == ) ans += mp[a[i].first];
  40. if (a[i].first == ) ++mp[a[i].second];
  41. }
  42.  
  43. for (int i = ; i <= n; i++)
  44. if (a[i].first == && a[i].second == ) ++ans;
  45.  
  46. printf("%lld\n", ans);
  47. return ;
  48. }

C

Graph And Its Complement

我觉得这是这场最有趣的一道题。

做出这个首先需要发现一条性质,$n, a, b$一定需要满足$a == 1$或者$b == 1$的形式才可能有解。

可能的意思是说在$a == 1$并且$b == 1$并且$n == 2 || n == 3$的时候无解。

假设原图有超过$1$个连通块,那么对于任意两个联通块来说,取补集之后都会有一条边相连,所以补图一定只有一个连通块。

如果$b$为$1$并且$a$不为$1$可以$swap$过来然后输出补图。

这样子把$1$到$n - a + 1$连成一条链就好了。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5.  
  6. const int N = ;
  7.  
  8. int n, a, b;
  9. bool ans[N][N];
  10.  
  11. int main() {
  12. scanf("%d%d%d", &n, &a, &b);
  13. if (a != && b != ) return puts("NO"), ;
  14. if (a == && b == ) {
  15. if (n == || n == ) return puts("NO"), ;
  16. for (int i = ; i < n; i++) ans[i][i + ] = ans[i + ][i] = ;
  17. puts("YES");
  18. for (int i = ; i <= n; i++, putchar('\n'))
  19. for (int j = ; j <= n; j++)
  20. putchar(ans[i][j] + '');
  21. return ;
  22. }
  23.  
  24. bool flag = ;
  25. if (a == ) swap(a, b), flag = ;
  26. if (flag) memset(ans, , sizeof(ans));
  27. for (int i = ; i <= n - a; i++) ans[i][i + ] ^= , ans[i + ][i] ^= ;
  28.  
  29. puts("YES");
  30. for (int i = ; i <= n; i++, putchar('\n'))
  31. for (int j = ; j <= n; j++) {
  32. if (i == j) putchar('');
  33. else putchar(ans[i][j] + '');
  34. }
  35.  
  36. return ;
  37. }

D

Post Lamps

这题我纠结了很长时间的第一个样例,因为怎么玩都有比样例输出更好的答案,直到我在$announcement$里面发现了这样一句话:

感觉无话可说……

先考虑没有“不能放”的限制的时候怎么做,对于每一个亮度$k$,贪心地把它放在$0, k, 2k, \cdots$直到大于等于$n$。

现在加入限制条件,考虑如果在跳的时候遇到了一个障碍,就尝试在这个障碍前面最近的一个不是障碍的位置放灯,如果这样还是不可以照亮它,那么直接无解。

障碍在$0$的时候可以直接无解。

可以用一个并查集,遇到障碍就把父指针指向前一个位置,这个并查集可以路径压缩。

注意到这个复杂度其实是一个调和级数,虽然并不是特别严格,但是根本跑不满。

应该比$D$简单吧。

  1. #include <cstdio>
  2. #include <cstring>
  3. using namespace std;
  4. typedef long long ll;
  5.  
  6. const int N = 1e6 + ;
  7. const ll inf = 1LL << ;
  8.  
  9. int n, m, k, ufs[N];
  10. ll a[N];
  11. bool b[N];
  12.  
  13. template <typename T>
  14. inline void read(T &X) {
  15. X = ; char ch = ; T op = ;
  16. for (; ch > ''|| ch < ''; ch = getchar())
  17. if (ch == '-') op = -;
  18. for (; ch >= '' && ch <= ''; ch = getchar())
  19. X = (X << ) + (X << ) + ch - ;
  20. X *= op;
  21. }
  22.  
  23. template <typename T>
  24. inline void chkMin(T &x, T y) {
  25. if (y < x) x = y;
  26. }
  27.  
  28. int find(int x) {
  29. return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
  30. }
  31.  
  32. int main() {
  33. read(n), read(m), read(k);
  34. for (int i = ; i <= n; i++) ufs[i] = i;
  35. for (int pos, i = ; i <= m; i++) {
  36. read(pos);
  37. if (pos == ) return puts("-1"), ;
  38. b[pos] = ;
  39. ufs[pos] = pos - ;
  40. }
  41. b[n] = , ufs[n] = n - ;
  42. for (int i = ; i <= k; i++) read(a[i]);
  43.  
  44. ll ans = inf;
  45. for (int i = ; i <= k; i++) {
  46. int cnt = ; ll res = ;
  47. for (int j = ; j < n; j += i) {
  48. if (!b[j]) ++cnt;
  49. else {
  50. int pos = find(ufs[j]);
  51. if (j - pos < i) ++cnt, j = pos;
  52. else {
  53. res = inf;
  54. break;
  55. }
  56. }
  57. }
  58. if (res != inf) res = 1LL * cnt * a[i];
  59. chkMin(ans, res);
  60. }
  61.  
  62. printf("%I64d\n", ans == inf ? - : ans);
  63. return ;
  64. }

E

Flow Control

虽然网络流已经差不多忘得一干二净了,但是流量守恒这一点还是能记住手玩出来的。

先把所有的$s_i$求和,如果不为$0$一定不合法。

注意到当有环的时候有一些边可以随便流,等价于就算这些边不存在(流量为$0$)也能出解。

所以做一棵生成树就好了,不在生成树中的边流量输出$0$。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. using namespace std;
  5. typedef long long ll;
  6. typedef pair <int, int> pin;
  7.  
  8. const int N = 2e5 + ;
  9.  
  10. int n, m, tot = , head[N], ufs[N], dep[N];
  11. ll a[N], sum[N];
  12. bool vis[N];
  13. pin pat[N];
  14.  
  15. struct Edge {
  16. int to, nxt;
  17. } e[N << ];
  18.  
  19. inline void add(int from, int to) {
  20. e[++tot].to = to;
  21. e[tot].nxt = head[from];
  22. head[from] = tot;
  23. }
  24.  
  25. template <typename T>
  26. inline void read(T &X) {
  27. X = ; char ch = ; T op = ;
  28. for (; ch > ''|| ch < ''; ch = getchar())
  29. if (ch == '-') op = -;
  30. for (; ch >= '' && ch <= ''; ch = getchar())
  31. X = (X << ) + (X << ) + ch - ;
  32. X *= op;
  33. }
  34.  
  35. int find(int x) {
  36. return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
  37. }
  38.  
  39. inline bool merge(int x, int y) {
  40. int fx = find(x), fy = find(y);
  41. if (fx == fy) return ;
  42. ufs[fx] = fy;
  43. return ;
  44. }
  45.  
  46. inline bool chk() {
  47. ll tmp = ;
  48. for (int i = ; i <= n; i++) tmp += a[i];
  49. return (!tmp);
  50. }
  51.  
  52. void dfs(int x, int fat, int depth) {
  53. dep[x] = depth, sum[x] = a[x];
  54. for (int i = head[x]; i; i = e[i].nxt) {
  55. int y = e[i].to;
  56. if (y == fat) continue;
  57. dfs(y, x, depth + );
  58. sum[x] += sum[y];
  59. }
  60. }
  61.  
  62. int main() {
  63. read(n);
  64. for (int i = ; i <= n; i++) {
  65. read(a[i]);
  66. ufs[i] = i;
  67. }
  68. read(m);
  69. for (int x, y, i = ; i <= m; i++) {
  70. read(x), read(y);
  71. pat[i].first = x, pat[i].second = y;
  72. if (!merge(x, y)) continue;
  73. vis[i] = ;
  74. add(x, y), add(y, x);
  75. }
  76.  
  77. if (!chk()) return puts("Impossible"), ;
  78.  
  79. dfs(, , );
  80.  
  81. puts("Possible");
  82. for (int i = ; i <= m; i++) {
  83. if (vis[i])
  84. printf("%lld\n", dep[pat[i].first] < dep[pat[i].second] ? sum[pat[i].second] : -sum[pat[i].first]);
  85. else puts("");
  86. }
  87.  
  88. return ;
  89. }

F

GCD Counting

因为统计的时候复杂度是只和$gcd$的个数有关的,所以可以直接大力点分治,复杂度也是没问题的。

但是点分治真的写不对这样太无脑了,考虑正解提到的稍微有一点技术含量的做法。

用$h(i)$表示树上能被$i$整除的路径的数量,注意到在树上一定是若干个满足条件的联通块选点之后求和。

一个$siz$为$n$的连通块的贡献是$\frac{n(n + 1)}{2}$。

那么最后的答案

$$ans_x = \sum_{i = x}^{\left \lfloor \frac{n}{x} \right \rfloor}\mu(i)h(xi)$$

我选择用一个并查集合并一下。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <vector>
  5. using namespace std;
  6. typedef long long ll;
  7.  
  8. const int N = 2e5 + ;
  9. const int Maxn = 2e5;
  10.  
  11. int n, a[N], tot = , head[N], fa[N];
  12. int pCnt = , pri[N], mu[N], ufs[N], siz[N];
  13. bool np[N], vis[N];
  14. ll ans[N], f[N];
  15. vector <int> h[N], vec;
  16.  
  17. struct Edge {
  18. int to, nxt;
  19. } e[N << ];
  20.  
  21. inline void add(int from, int to) {
  22. e[++tot].to = to;
  23. e[tot].nxt = head[from];
  24. head[from] = tot;
  25. }
  26.  
  27. template <typename T>
  28. inline void read(T &X) {
  29. X = ; char ch = ; T op = ;
  30. for (; ch > ''|| ch < ''; ch = getchar())
  31. if (ch == '-') op = -;
  32. for (; ch >= '' && ch <= ''; ch = getchar())
  33. X = (X << ) + (X << ) + ch - ;
  34. X *= op;
  35. }
  36.  
  37. inline void sieve() {
  38. mu[] = ;
  39. for (int i = ; i <= Maxn; i++) {
  40. if (!np[i])
  41. pri[++pCnt] = i, mu[i] = -;
  42. for (int j = ; j <= pCnt && pri[j] * i <= Maxn; j++) {
  43. np[i * pri[j]] = ;
  44. if (i % pri[j] == ) {
  45. mu[i * pri[j]] = ;
  46. break;
  47. }
  48. mu[i * pri[j]] = -mu[i];
  49. }
  50. }
  51. }
  52.  
  53. void dfs(int x, int fat) {
  54. fa[x] = fat;
  55. for (int i = head[x]; i; i = e[i].nxt) {
  56. int y = e[i].to;
  57. if (y == fat) continue;
  58. dfs(y, x);
  59. }
  60. }
  61.  
  62. int find(int x) {
  63. return ufs[x] == x ? x : ufs[x] = find(ufs[x]);
  64. }
  65.  
  66. inline bool merge(int x, int y) {
  67. int fx = find(x), fy = find(y);
  68. if (fx == fy) return ;
  69. if (siz[fx] < siz[fy]) ufs[fx] = fy, siz[fy] += siz[fx];
  70. else ufs[fy] = fx, siz[fx] += siz[fy];
  71. return ;
  72. }
  73.  
  74. int main() {
  75. sieve();
  76.  
  77. read(n);
  78. for (int i = ; i <= n; i++) {
  79. read(a[i]);
  80. h[a[i]].push_back(i);
  81. }
  82. for (int x, y, i = ; i < n; i++) {
  83. read(x), read(y);
  84. add(x, y), add(y, x);
  85. }
  86. dfs(, );
  87.  
  88. for (int i = ; i <= Maxn; i++) {
  89. for (int j = i; j <= Maxn; j += i)
  90. for (int k = ; k < (int)h[j].size(); k++) {
  91. int x = h[j][k];
  92. ufs[x] = x, siz[x] = , vis[x] = ;
  93. vec.push_back(x);
  94. }
  95.  
  96. for (int j = ; j < (int)vec.size(); j++) {
  97. int x = vec[j];
  98. if (fa[x] && a[fa[x]] % i == ) merge(x, fa[x]);
  99. }
  100.  
  101. for (int j = ; j < (int)vec.size(); j++) {
  102. int x = vec[j], fx = find(x);
  103. if (vis[fx]) continue;
  104. f[i] += 1LL * siz[fx] * (siz[fx] + ) / ;
  105. vis[fx] = ;
  106. }
  107.  
  108. vec.clear();
  109. }
  110.  
  111. for (int i = ; i <= Maxn; i++)
  112. for (int j = i; j <= Maxn; j += i)
  113. ans[i] += 1LL * mu[j / i] * f[j];
  114.  
  115. for (int i = ; i <= Maxn; i++) {
  116. if (!ans[i]) continue;
  117. printf("%d %I64d\n", i, ans[i]);
  118. }
  119.  
  120. return ;
  121. }

G

CF 990 Educational Codeforces Round 45的更多相关文章

  1. Educational Codeforces Round 45 (Div 2) (A~G)

    目录 Codeforces 990 A.Commentary Boxes B.Micro-World C.Bracket Sequences Concatenation Problem D.Graph ...

  2. Educational Codeforces Round 45 (Rated for Div. 2) C、D

      C. Bracket Sequences Concatenation Problem time limit per test 2 seconds memory limit per test 256 ...

  3. Educational Codeforces Round 45 (Rated for Div. 2) E - Post Lamps

    E - Post Lamps 思路:一开始看错题,以为一个地方不能重复覆盖,我一想值这不是sb题吗,直接每个power check一下就好....复杂度nlogn 然后发现不是,这样的话,对于每个po ...

  4. Educational Codeforces Round 45 (Rated for Div. 2) G - GCD Counting

    G - GCD Counting 思路:我猜测了一下gcd的个数不会很多,然后我就用dfs回溯的时候用map暴力合并就好啦. 终判被卡了MLE.....  需要每次清空一下子树的map... #inc ...

  5. Educational Codeforces Round 45 (Rated for Div. 2) F - Flow Control

    F - Flow Control 给你一个有向图,要求你给每条边设置流量,使得所有点的流量符合题目给出的要求. 思路:只有在所有点的流量和为0时有解,因为增加一条边的值不会改变所有点的总流量和, 所以 ...

  6. Educational Codeforces Round 45 (Rated for Div. 2)

    A bracket sequence is a string containing only characters "(" and ")". A regular ...

  7. Educational Codeforces Round 45

    A. 一个小模拟    不解释 //By SiriusRen #include <bits/stdc++.h> using namespace std; long long n,m,a,b ...

  8. [Educational Codeforces Round 16]E. Generate a String

    [Educational Codeforces Round 16]E. Generate a String 试题描述 zscoder wants to generate an input file f ...

  9. [Educational Codeforces Round 16]D. Two Arithmetic Progressions

    [Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...

随机推荐

  1. emmc boot_config文件不存在

    /******************************************************************************* * emmc boot_config文 ...

  2. python3 openpyxl基本操作

    #coding:utf-8 import xlrd import xlwt # 读写2007 excel import openpyxl import sys #读取设备sn # def readSN ...

  3. 浅谈iOS学习之路(转)

    转眼学习iOS已经快两年的时间了,这个路上有挫折也有喜悦,一步步走过来发现这个过程是我这一辈子的财富,我以前的老大总是对我说,年轻就是最大的资本(本人91年),现在才算是慢慢的体会到,反观自己走过的这 ...

  4. ajax请求返回Json字符串运用highcharts数据图表展现数据

    [1].[图片] Json字符串和highcharts数据图表展现.jpg 跳至 [1] code=26754#44745" rel="nofollow"> [2] ...

  5. Spring集成Mybatis(Dao方式开发)

    Spring整成Mybatis注意事项:  1. 关键jar包不能少 2.可以单独整理好Mybatis框架,测试无误再集成Spring 3.集成时,参数级别的细节可以选择忽略,但思路必须清晰 代码如下 ...

  6. hadoop YARN配置参数剖析—MapReduce相关参数

    MapReduce相关配置参数分为两部分,分别是JobHistory Server和应用程序参数,Job History可运行在一个独立节点上,而应用程序参数则可存放在mapred-site.xml中 ...

  7. bzoj 5020(洛谷4546) [THUWC 2017]在美妙的数学王国中畅游——LCT+泰勒展开

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5020 https://www.luogu.org/problemnew/show/P4546 ...

  8. 打印进度条——(progress bar才是专业的)

    # 打印进度条——(progress bar是专业的) import time for i in range(0,101,2): time.sleep(0.1) char_num = i//2 #打印 ...

  9. Django 组件-分页器

    Django的分页器(paginator) view from django.shortcuts import render,HttpResponse # Create your views here ...

  10. HDU 1358 Period (kmp判断循环子串)

    Period Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 65536/32768K (Java/Other) Total Submis ...