[关闭]
@Dmaxiya 2018-08-17T10:16:35.000000Z 字数 5838 阅读 1110

Codeforces Round #470 (Div. 1)

Codeforces


Contests 链接:Codeforces Round #470 (Div. 1)
过题数:3
排名:315/1183

A. Primal Sport

题意

两人在玩一个游戏, 先开始,两人轮流进行,第 次游戏中,对于一个整数 ,选择一个素数 ,然后找到一个最小的整数 ,使得 能被 整除,将这个数字作为下一次游戏的新值 继续进行游戏,现在游戏已经进行了两次,得到了 的值,问最小的可能的 的值为多少。

输入

输入为一个整数 ,数据保证 是合数。

输出

输出最小的可能的 的值。

样例

输入
14
输出
6
提示
,则其中一种合法的游戏过程如下:
1. 选择 的值为
2. 选择 的值为
输入
20
输出
15
提示
,则其中一种合法的游戏过程如下:
1. 选择 的值为
2. 选择 的值为
输入
8192
输出
8191

题解

我们可以根据 的值确定 的合法的取值区间:,其中 的最大的质因子,对于 的值,只要选择质数 就可以通过 得到 的值,对于 的值,如果选择质数 ,则只能得到 的值,如果选择其他质数,由于 是最大的质因数,选择其他质数能够改变的增量一定小于 ,所以 。但是最小的 并不能得到最小的 ,因此对于 我们需要枚举所有可能的 的值,来找到最小的 的值。

过题代码

  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 = 1000000 + 100;
  21. int cnt, n;
  22. bool vis[maxn];
  23. int prime[maxn];
  24. void Prime() {
  25. for(int i = 2; i < maxn; ++i) {
  26. if(!vis[i]) {
  27. prime[cnt++] = i;
  28. }
  29. for(int j = 0; j < cnt && i < maxn / prime[j]; ++j) {
  30. int k = i * prime[j];
  31. vis[k] = true;
  32. if(i % prime[j] == 0) {
  33. break;
  34. }
  35. }
  36. }
  37. }
  38. int Find(int x) {
  39. int ret;
  40. int xx = x;
  41. for(int i = 0; i < cnt && prime[i] <= xx / prime[i]; ++i) {
  42. while(x % prime[i] == 0) {
  43. x /= prime[i];
  44. ret = prime[i];
  45. }
  46. }
  47. if(x != 1) {
  48. ret = x;
  49. }
  50. return ret;
  51. }
  52. int main() {
  53. #ifdef LOCAL
  54. freopen("test.txt", "r", stdin);
  55. // freopen("out.txt", "w", stdout);
  56. #endif // LOCAL
  57. ios::sync_with_stdio(false);
  58. Prime();
  59. while(scanf("%d", &n) != EOF) {
  60. int Start = Find(n);
  61. int ans = INT_MAX;
  62. for(int i = n - Start + 1; i <= n; ++i) {
  63. int tmp = i - Find(i) + 1;
  64. if(tmp >= 3) {
  65. ans = min(ans, tmp);
  66. }
  67. }
  68. printf("%d\n", ans);
  69. }
  70. return 0;
  71. }

B. Producing Snow

题意

从第 天到第 天每天堆体积为 体积的雪人,第 天的时候每一个已经堆好的雪人会融化 的体积,问在第 天当天所有已经堆好的且没有完全融化的雪人会融化的总的体积。

输入

第一行包含一个整数 ,第 行包含 个整数 ,第 行包含 个整数

输出

输出 个整数,第 个整数表示第 天融化的雪人体积。

样例

输入
3
10 10 5
5 7 2
输出
5 12 4
提示
第一天堆了一个体积为 的雪人,融化了 的体积,剩下一个体积为 的雪人,第二天堆了一个体积为 的雪人,每个雪人都融化 的体积,第一天的 体积的雪人全都融化了,第二天的雪人融化了 体积,总共融化了 体积,第二天只剩下一个体积为 的雪人,第三天堆了一个体积为 的雪人,第二天雪人剩下的体积和第三天雪人的体积都大于等于第三天融化的体积,第三天总共融化了 体积的雪人。
输入
5
30 25 20 15 10
9 10 12 4 13
输出
9 20 35 11 25

题解

假设第 天堆起来的雪人体积为无穷大,那么到第 天的时候这个雪人融化的体积就为 ,第 天刚堆起来的雪人没有受到前 天融化的影响,但是可以假设这个雪人是从第 天堆起来的,第 天的时候融化了 的体积,导致它第 天的体积为 ,因此可以认为这个雪人在第 天堆起来的时候的体积为 ,我们将到第 天的所有雪人的体积都转化为 后放入 中,到第 天完全融化的雪人就是 的雪人,将这些雪人在第 天融化的体积()计算出来,然后从 中删去它们,再计算第 天能融化体积 的雪人的个数 (可以 维护),于是第 天融化的雪人体积就为 ,其中

过题代码

  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, cnt;
  22. LL mp_cnt;
  23. map<LL, int> mp;
  24. map<LL, int>::iterator it, itt;
  25. LL v[maxn], t[maxn];
  26. map<LL, int>::iterator del[maxn];
  27. int main() {
  28. #ifdef LOCAL
  29. freopen("test.txt", "r", stdin);
  30. // freopen("out.txt", "w", stdout);
  31. #endif // LOCAL
  32. ios::sync_with_stdio(false);
  33. while(scanf("%d", &n) != EOF) {
  34. mp_cnt = 0;
  35. for(int i = 1; i <= n; ++i) {
  36. scanf("%I64d", &v[i]);
  37. }
  38. for(int i = 1; i <= n; ++i) {
  39. scanf("%I64d", &t[i]);
  40. t[i] += t[i - 1];
  41. }
  42. mp.clear();
  43. LL ans;
  44. for(int i = 1; i <= n; ++i) {
  45. ans = 0;
  46. cnt = 0;
  47. v[i] += t[i - 1];
  48. ++mp[v[i]];
  49. ++mp_cnt;
  50. it = mp.upper_bound(t[i]);
  51. for(itt = mp.begin(); itt != it; ++itt) {
  52. ans += ((itt->first) - t[i - 1]) * (itt->second);
  53. del[cnt++] = itt;
  54. mp_cnt -= itt->second;
  55. }
  56. for(int j = 0; j < cnt; ++j) {
  57. mp.erase(del[j]);
  58. }
  59. ans += mp_cnt * (t[i] - t[i - 1]);
  60. if(i != 1) {
  61. printf(" ");
  62. }
  63. printf("%I64d", ans);
  64. }
  65. printf("\n");
  66. }
  67. return 0;
  68. }

C. Perfect Security

题意

有两个长度为 的序列 ,对于每一个 ,在 序列中找到一个数字与其异或,成为新序列的第 个元素 ,然后从 序列中删去被选中的数字,求能够构成的新序列中字典序最小的序列。

输入

第一行包含一个整数 ,第二行为 个整数 ,第三行为 个整数

输出

输出 个整数,第 个整数表示所求新序列的第 项。

样例

输入
3
8 4 13
17 2 7
输出
10 3 28
提示
。对于其他可能的答案:,都比 的字典序大。
输入
5
12 7 87 22 11
18 39 9 12 16
输出
0 14 69 6 44
输入
10
331415699 278745619 998190004 423175621 42983144 166555524 843586353 802130100 337889448 685310951
226011312 266003835 342809544 504667531 529814910 684873393 817026985 844010788 993949858 1031395667
输出
128965467 243912600 4281110 112029883 223689619 76924724 429589 119397893 613490433 362863284

题解

将所有 序列中的数字建一棵字典树,从 对于每一个 ,都取一个 序列中与 异或值最小的,然后将这个数字在字典树中出现的次数

过题代码

  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 maxm = 300000 + 100;
  21. const int maxn = 300000 * 32 + 100;
  22. const int Size = 2;
  23. struct Trie {
  24. int root, cnt;
  25. int val[maxn], tree[maxn][Size];
  26. int creat() {
  27. ++cnt;
  28. memset(tree[cnt], 0, sizeof(tree[cnt]));
  29. val[cnt] = 0;
  30. return cnt;
  31. }
  32. void Init() {
  33. cnt = 0;
  34. root = creat();
  35. }
  36. int id(int x, int dig) {
  37. return ((x >> (31 - dig)) & 1);
  38. }
  39. void add(int x) {
  40. int pos = root;
  41. for(int i = 0; i < 32; ++i) {
  42. int w = id(x, i);
  43. if(tree[pos][w] == 0) {
  44. tree[pos][w] = creat();
  45. }
  46. pos = tree[pos][w];
  47. ++val[pos];
  48. }
  49. }
  50. int query(int x) {
  51. int ret = 0;
  52. int pos = root;
  53. for(int i = 0; i < 32; ++i) {
  54. int w = id(x, i);
  55. if(tree[pos][w] == 0 || val[tree[pos][w]] == 0) {
  56. w = !w;
  57. ret |= (1 << (31 - i));
  58. }
  59. pos = tree[pos][w];
  60. --val[pos];
  61. }
  62. return ret;
  63. }
  64. };
  65. Trie t;
  66. int n, x;
  67. int num[maxn];
  68. int main() {
  69. #ifdef LOCAL
  70. freopen("test.txt", "r", stdin);
  71. // freopen("out.txt", "w", stdout);
  72. #endif // LOCAL
  73. ios::sync_with_stdio(false);
  74. while(scanf("%d", &n) != EOF) {
  75. t.Init();
  76. for(int i = 0; i < n; ++i) {
  77. scanf("%d", &num[i]);
  78. }
  79. for(int i = 0; i < n; ++i) {
  80. scanf("%d", &x);
  81. t.add(x);
  82. }
  83. for(int i = 0; i < n; ++i) {
  84. if(i != 0) {
  85. printf(" ");
  86. }
  87. printf("%d", t.query(num[i]));
  88. }
  89. printf("\n");
  90. }
  91. return 0;
  92. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注