[关闭]
@Dmaxiya 2018-08-17T10:21:29.000000Z 字数 5821 阅读 965

Codeforces Round #445 (Div. 2)

Codeforces


Contests 链接:Codeforces Round #445 (Div. 2)
过题数:3
排名:315/5849

A. ACM ICPC

题意

给定 个数字,问是否存在一种平分的方式,使得其中 个数的和等于另外 个数的和。

输入

输入包含 个整数

输出

如果存在,则输出 ,否则输出 ,大小写任意。

样例

输入 输出 提示
1 3 2 1 2 1 YES 将第 个、第 个和第 个数字分到一起,则
1 1 1 1 1 99 NO 个数字太大,因此无法达到要求。

题解

生成 个数字的全排列,对于每一种排列,判断前 个数字的和的 倍是否等于 个数字的和。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 100;
  23. int num[maxn];
  24. int main() {
  25. #ifdef LOCAL
  26. freopen("test.txt", "r", stdin);
  27. // freopen("out.txt", "w", stdout);
  28. #endif
  29. ios::sync_with_stdio(false);
  30. while(scanf("%d", &num[0]) != EOF) {
  31. bool flag = false;
  32. int sum = num[0];
  33. for(int i = 1; i < 6; ++i) {
  34. scanf("%d", &num[i]);
  35. sum += num[i];
  36. }
  37. sort(num, num + 6);
  38. do {
  39. int tmp = 0;
  40. for(int i = 0; i < 3; ++i) {
  41. tmp += num[i];
  42. }
  43. if(tmp * 2 == sum) {
  44. flag = true;
  45. break;
  46. }
  47. } while(next_permutation(num, num + 6));
  48. if(flag) {
  49. printf("YES\n");
  50. } else {
  51. printf("NO\n");
  52. }
  53. }
  54. return 0;
  55. }

B. Vlad and Cafes

题意

给定一个长度为 的序列 ,在序列中查找一个数字,要求每个其他数字最后一次出现的位置都在这个数字最后一次出现的位置之后。

输入

第一行为一个整数 ,第二行为 个整数

输出

输出满足条件的数字。

样例

输入 输出 提示
5
1 3 2 1 2
3 在数字 最后一次出现的位置都在数字 最后一次出现的位置后面。
6
2 1 2 2 4 1
2 数字 最后一次出现的位置都在数字 最后一次出现的位置之后。

题解

先将所有数字都放入一个 当中,再从后往前从 中删除数字,当 为空时,说明所有数字的最后一次出现的位置都已经扫到,最后一个被删除的数字就是答案。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 200000 + 100;
  23. int n, ans;
  24. int num[maxn];
  25. set<int> st;
  26. int main() {
  27. #ifdef LOCAL
  28. freopen("test.txt", "r", stdin);
  29. // freopen("out.txt", "w", stdout);
  30. #endif
  31. ios::sync_with_stdio(false);
  32. while(scanf("%d", &n) != EOF) {
  33. st.clear();
  34. for(int i = 1; i <= n; ++i) {
  35. scanf("%d", &num[i]);
  36. st.insert(num[i]);
  37. }
  38. for(int i = n; i > 0; --i) {
  39. st.erase(num[i]);
  40. if(st.empty()) {
  41. ans = num[i];
  42. break;
  43. }
  44. }
  45. printf("%d\n", ans);
  46. }
  47. return 0;
  48. }

C. Petya and Catacombs

题意

在一个有 个节点的地下墓穴中探险,节点与节点之间存在通道,有些通道可能是连接到同一个节点上的, 经过每条通道的时间都是一分钟,在探险的过程中, 会在自己的笔记本上按下面的规则做笔记:

  1. 如果 在第 分钟到达某个节点,而他之前已经到达过这个节点,就会在笔记本上的第 个位置记下上次到达这个节点的时间 ,而将到达这个节点的时间更新为
  2. 如果 到达了一个之前从未到达过的节点,他就会记下任何一个小于当前时间 的正整数为

最开始(第 分钟) 在任意一个节点上,且他不会记录下 探险结束后就扔下了他的笔记本,而 捡到了他的笔记本, 想知道在按照上面的规则记录数字的情况下, 最少走到了多少个节点。

输入

第一行为一个整数 ,表示 在笔记本上记录下的数字个数,第二行为 个整数

输出

输出一个整数,表示 最少可能经过的节点数。

样例

输入 输出 提示
2
0 0
2 可能经历的节点顺序为: 或者 ,其中最少的节点数为
5
0 1 0 1 3
3 可能经历的节点顺序为:

题解

对于每次记录,贪心地能够回到已经到达过的节点就让 回去,而判断已经到达过的节点的方式,就是判断在经过的洞穴中,存在上一次到达时间等于 的数字,并将这个数字更新为 ,用 来实现会方便很多,最终的答案就是 的大小。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. int n, num;
  23. set<int> st;
  24. int main() {
  25. #ifdef LOCAL
  26. freopen("test.txt", "r", stdin);
  27. // freopen("out.txt", "w", stdout);
  28. #endif
  29. ios::sync_with_stdio(false);
  30. while(scanf("%d", &n) != EOF) {
  31. st.clear();
  32. for(int i = 1; i <= n; ++i) {
  33. scanf("%d", &num);
  34. st.erase(num);
  35. st.insert(i);
  36. }
  37. printf("%d\n", (int)st.size());
  38. }
  39. return 0;
  40. }

D. Restoration of string

题意

如果一个字符串在另一个字符串中出现的次数是最多的,那么这个字符串就是最频繁子串,现在给定 个字符串,,要求构造一个字符串,使得每一个 都是构造出来的字符串的最频繁字串。

输入

第一行为一个整数 ,接下去 行每行为一个字符串

输出

输出满足条件的字符串,如果有多个答案则输出长度最小的字符串,如果仍然有多个,则输出字典序最小的字符串。

样例

输入 输出 提示
4
mail
ai
lru
cf
cfmailru 只有两个满足条件的长度最短的字符串:"cfmailru" 和 "mailrucf",而第一个的字典序是最小的。
3
kek
preceq
cheburek
NO

题解

对于每个给出的字符串,在任意两个相邻字符之间连一条有向边,这样所有的字符串就可以连接成一张有向图,而这张有向图必须为一条链:

  1. 如果有向图存在环则无论多长的字符串都无法满足条件,例如 "ab" 和 "ba",构造出的字符串无论有多长,其中一个子串出现的次数总是比另一个大
  2. 如果有向图存在岔路,则无法构造出该字符串或者有一个字符重复出现的情况,如 "ab" 和 "ac",无论是 "abc" 或是 "acb" 都无法满足条件,而 "abac" 将使得 "ab" 和 "ac" 都不是最频繁子串,"a" 才是最频繁子串。
    在满足构造出的有向图是一条链的情况下,按照字典序输出答案即可。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cfloat>
  7. #include <cstring>
  8. #include <string>
  9. #include <vector>
  10. #include <list>
  11. #include <queue>
  12. #include <stack>
  13. #include <map>
  14. #include <set>
  15. #include <bitset>
  16. #include <algorithm>
  17. #include <ctime>
  18. #include <functional>
  19. #include <iomanip>
  20. using namespace std;
  21. #define LL long long
  22. const int maxn = 100000 + 100;
  23. const int maxm = 30;
  24. int n;
  25. int degin[maxm], degout[maxm];
  26. bool head[maxm];
  27. char str[maxn];
  28. bool G[maxm][maxm];
  29. queue<int> que;
  30. int id(char ch) {
  31. return ch - 'a';
  32. }
  33. bool topsort() {
  34. for(int i = 0; i < 26; ++i) {
  35. if(degin[i] == 0) {
  36. que.push(i);
  37. }
  38. }
  39. while(!que.empty()) {
  40. int tmp = que.front();
  41. que.pop();
  42. for(int i = 0; i < 26; ++i) {
  43. if(G[tmp][i]) {
  44. --degin[i];
  45. if(degin[i] == 0) {
  46. que.push(i);
  47. }
  48. }
  49. }
  50. }
  51. for(int i = 0; i < 26; ++i) {
  52. if(degin[i] != 0) {
  53. return false;
  54. }
  55. }
  56. return true;
  57. }
  58. int main() {
  59. #ifdef LOCAL
  60. freopen("test.txt", "r", stdin);
  61. // freopen("out.txt", "w", stdout);
  62. #endif
  63. ios::sync_with_stdio(false);
  64. while(scanf("%d", &n) != EOF) {
  65. memset(head, 0, sizeof(head));
  66. memset(degin, 0, sizeof(degin));
  67. memset(degout, 0, sizeof(degout));
  68. memset(G, 0, sizeof(G));
  69. for(int i = 0; i < n; ++i) {
  70. scanf("%s", str);
  71. head[id(str[0])] = true;
  72. for(int j = 1; str[j]; ++j) {
  73. int u = id(str[j - 1]);
  74. int v = id(str[j]);
  75. if(!G[u][v]) {
  76. G[u][v] = true;
  77. ++degin[v];
  78. ++degout[u];
  79. }
  80. }
  81. }
  82. bool flag = true;
  83. for(int i = 0; i < 26; ++i) {
  84. if(degin[i] > 1 || degout[i] > 1) {
  85. flag = false;
  86. break;
  87. }
  88. }
  89. memcpy(degout, degin, sizeof(degin));
  90. if(!topsort()) {
  91. flag = false;
  92. }
  93. if(!flag) {
  94. printf("NO\n");
  95. continue;
  96. }
  97. for(int i = 0; i < 26; ++i) {
  98. if(degout[i] == 0 && head[i]) {
  99. flag = true;
  100. int pos = i;
  101. while(flag) {
  102. flag = false;
  103. printf("%c", pos + 'a');
  104. for(int j = 0; j < 26; ++j) {
  105. if(G[pos][j]) {
  106. pos = j;
  107. flag = true;
  108. break;
  109. }
  110. }
  111. }
  112. }
  113. }
  114. printf("\n");
  115. }
  116. return 0;
  117. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注