[关闭]
@Dmaxiya 2018-08-17T10:17:23.000000Z 字数 7267 阅读 1012

Codeforces Round #468 (Div. 2)

Codeforces


Contests 链接:Codeforces Round #468 (Div. 2)
过题数:4
排名:287/7914

A. Friends Meeting

题意

有两个人分别站在 的位置,两个人走第 步需要消耗 点体力,求要使两人相遇两人的最小总体力消耗值。

输入

输入第一行为一个整数 ,第二行为一个整数 ,其中

输出

输出最小总体力消耗。

样例

输入 输出 提示
3
4
1 第一个人往右移动一步,或者第二个人往左移动一步,两种走法需要消耗的体力总和都为
101
99
2 两个人各往中间走一步,他们将会在 处相遇,并且总体力消耗为
5
10
9 其中一种最优的方案是:第一个人向右移动 步,第二个人向左移动 步,他们将在
处相遇,且总消耗为

题解

暴力从 枚举相遇点,计算总贡献,取最小值。

过题代码

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

B. World Cup

题意

世界杯的比赛按两队之间进行比赛的淘汰制,最初 队和 队进行比赛, 队和 队进行比赛……获胜的队伍进入下一轮比赛, 队和 队中的胜利队伍和 队与 队的获胜队伍进行比赛……不断淘汰队伍,直到剩下最后一支队伍。问第 支队伍和第 支队伍可能会在第几场比赛相遇。

输入

输入包含三个整数 ,数据保证在任意轮次的比赛中都会有偶数支队伍进行比赛且

输出

如果 队和 队在总决赛之前相遇,输出他们相遇的比赛轮数,否则输出 "Final!"。

样例

输入 输出 提示
4 1 2 1
8 2 6 Final! 如果 队和 队在相遇之前的所有比赛都获胜,那么他们将会在第 轮比赛中相遇,
这一轮比赛是总决赛,因此应该输出 "Final"。
8 7 5 2

题解

根据比赛的队伍编号和比赛淘汰规则可以发现,每轮比赛相当于在高位相同低位不同的二进制数中选出其中一个数字,因此可以用二进制模拟,最后判断总决赛的轮数是否等于 队和 队相遇的轮数即可。

过题代码

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

C. Laboratory Work

题意

给定一个长度为 的整数序列 ,要求构造一个长度为 的整数序列使得新序列的平均值等于原序列的平均值,新序列的最大值和最小值不能超过原序列的最大值与最小值的范围,且新序列和原序列相同数字的个数最少。

输入

输入第一行包含一个整数 ,第二行包含 个整数 ,数据保证

输出

第一行输出一个整数,表示新构造的序列和原序列相同的数字个数,第二行为 个整数,表示新序列的每个数字,如果有多解输出任意一个。

样例

输入 输出 提示
6
-1 1 1 0 0 -1
2
0 0 0 0 0 0
原序列的平均值为 ,新序列的平均值也为 ,且两个序列
只有 个数字相同。
3
100 100 101
3
101 100 100
原序列和新序列只能完全相同,这样就有 个数字和原序列
相同。
7
-10 -9 -10 -8 -10 -9 -9
5
-10 -10 -9 -9 -9 -9 -9

题解

如果原序列的 ,则只能输出原序列,否则在以下两种方案中选择一种相同数字个数最少的:
1. 把 表示与最小值相等的数字个数, 则为与最大值相等的数字个数)个最小值与最大值都转化为
2. 把 个中间值()转化为 值, 个中间值转化为 值。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 100000 + 100;
  21. int n, Min, Max;
  22. int cnt[10];
  23. int num[maxn], ans;
  24. set<int> st;
  25. set<int>::iterator it;
  26. int main() {
  27. #ifdef LOCAL
  28. freopen("test.txt", "r", stdin);
  29. // freopen("out.txt", "w", stdout);
  30. #endif // LOCAL
  31. ios::sync_with_stdio(false);
  32. while(scanf("%d", &n) != EOF) {
  33. st.clear();
  34. ans = 0;
  35. memset(cnt, 0, sizeof(cnt));
  36. for(int i = 0; i < n; ++i) {
  37. scanf("%d", &num[i]);
  38. st.insert(num[i]);
  39. }
  40. it = st.begin();
  41. Min = *it;
  42. it = st.end();
  43. --it;
  44. Max = *it;
  45. if(Min == Max || Max - 1 == Min) {
  46. printf("%d\n", n);
  47. for(int i = 0; i < n; ++i) {
  48. if(i != 0) {
  49. printf(" ");
  50. }
  51. printf("%d", num[i]);
  52. }
  53. printf("\n");
  54. continue;
  55. }
  56. int Mid = Max - 1;
  57. int dx = 0;
  58. for(int i = 0; i < n; ++i) {
  59. dx += num[i] - Mid;
  60. ++cnt[num[i] - Min];
  61. }
  62. if(2 * min(cnt[0], cnt[2]) > cnt[1] / 2 * 2) {
  63. ans = min(cnt[0], cnt[2]) * 2;
  64. cnt[0] -= ans / 2;
  65. cnt[2] -= ans / 2;
  66. cnt[1] += ans;
  67. } else {
  68. ans = cnt[1] / 2 * 2;
  69. cnt[0] += ans / 2;
  70. cnt[2] += ans / 2;
  71. cnt[1] -= ans;
  72. }
  73. printf("%d\n", n - ans);
  74. int ccnt = 0;
  75. for(int i = 0; i < cnt[0]; ++i, ++ccnt) {
  76. if(ccnt != 0) {
  77. printf(" ");
  78. }
  79. printf("%d", Min);
  80. }
  81. for(int i = 0; i < cnt[1]; ++i, ++ccnt) {
  82. if(ccnt != 0) {
  83. printf(" ");
  84. }
  85. printf("%d", Mid);
  86. }
  87. for(int i = 0; i < cnt[2]; ++i, ++ccnt) {
  88. if(ccnt != 0) {
  89. printf(" ");
  90. }
  91. printf("%d", Max);
  92. }
  93. printf("\n");
  94. }
  95. return 0;
  96. }

D. Peculiar apple-tree

题意

有一棵 个节点 条边的树,树根为 ,且在底下,树叶在顶端(也就是一棵倒过来的树),每个节点上都有一个苹果,每一秒第 层(从下往上数)的苹果就会滚落到第 层,每两个苹果滚落到同一个节点上,它们就会相互抵消,问最后能够收获到多少个苹果。

输入

第一行为一个整数 ,第二行为 个整数 ,表示第 个几点的父节点是

输出

输出最终能在树根收获的苹果数。

样例

输入 输出 提示
3
1 1
1
5
1 2 2 2
3
18
1 1 1 4 4 3 2 2 2 10 8 9 9 9 10 10 4
4

题解

统计每一层树上的节点数量,如果是奇数,这一层就能收获一个苹果,否则就无法收获苹果,最后求和就是答案。

过题代码

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

E. Game with String

题意

对于一个给定的字符串 在这个字符串的基础上进行一个游戏,两个人都知道最初的字符串是什么,现在 将选择一个整数 ,将字符串循环左移 位生成一个新的字符串 ,即:将字符串 变为 不知道 的值,也不知道新的字符串 是什么样的,但是 可以告诉 字符串 的第一个字符, 也有一次询问的机会,询问新字符串的第 位是什么字符,问如果 采取最优的询问策略,她能通过这两个信息唯一确定 值的概率。

输入

输入为一个只包含小写字母的字符串

输出

输出 能唯一确定 值的概率,误差在 就认为程序正确。

样例

输入 输出 提示
technocup 1.000000000000000 不论 为何值, 只要通过询问新字符串的第二个字符,就能唯一地确定 的值,因此概率为
tictictactac 0.333333333333333 如果新字符串的第一个字符为 t 或者 c,那么 无法通过一次询问唯一地确定 的值,如果新字符串的第一个字符为 i 或者 a 就可以通过询问新字符串的第 个字符来唯一地确定 的值。
bbaabaabbb 0.100000000000000

题解

定义 (这里 仅仅是为了区别于 )为在原字符串中,从字符 往右 个位置的字符为 (如果下标超过 则从 开始继续往右),只有当 的值为 时, 才能在看到新字符串的第一个字符为 、询问得到第 个位置的字符为 时,唯一地确定 的值。但是由于字符 往右移动 位能够到达的字符 有许多个,为了让唯一确定 值的概率尽可能地大, 应该询问向右移动 位后,得到的唯一不同的字符 的数量尽可能多的位置,询问这些 的值,才可能唯一确定尽可能多的 ,最后将这些能唯一确定的字符位置个数相加,除以字符串的长度,就是能唯一确定 值的概率。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <climits>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <list>
  10. #include <queue>
  11. #include <stack>
  12. #include <map>
  13. #include <set>
  14. #include <bitset>
  15. #include <algorithm>
  16. #include <functional>
  17. #include <iomanip>
  18. using namespace std;
  19. #define LL long long
  20. const int maxn = 5000 + 100;
  21. char str[maxn];
  22. int ccnt[26];
  23. int num[30][maxn][30];
  24. int main() {
  25. #ifdef LOCAL
  26. freopen("test.txt", "r", stdin);
  27. // freopen("out.txt", "w", stdout);
  28. #endif // LOCAL
  29. ios::sync_with_stdio(false);
  30. memset(ccnt, 0, sizeof(ccnt));
  31. scanf("%s", str);
  32. int len = strlen(str);
  33. for(int i = 0; i < len; ++i) {
  34. for(int j = 1; j < len; ++j) {
  35. int Index = (i + j) % len;
  36. ++num[str[i] - 'a'][j][str[Index] - 'a'];
  37. }
  38. }
  39. for(int i = 0; i < 26; ++i) {
  40. for(int j = 1; j < len; ++j) {
  41. int cnt = 0;
  42. for(int k = 0; k < 26; ++k) {
  43. if(num[i][j][k] == 1) {
  44. ++cnt;
  45. }
  46. }
  47. ccnt[i] = max(ccnt[i], cnt);
  48. }
  49. }
  50. int ans = 0;
  51. for(int i = 0; i < 26; ++i) {
  52. ans += ccnt[i];
  53. }
  54. printf("%.10f\n", (double)ans / len);
  55. return 0;
  56. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注