[关闭]
@Dmaxiya 2018-08-17T10:24:30.000000Z 字数 5406 阅读 991

Codeforces Round #422 (Div. 2)

Codeforces


Contests 链接:Codeforces Round #422 (Div. 2)
过题数:2
排名:1873/13732

A. I'm bored with life

题意

,其中

输入

输入包含两个整数

输出

输出 的最大公约数。

样例

输入 输出 提示
4 3 6 ,所以

题解

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  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 <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 13;
  18. int A, B;
  19. LL fac[maxn];
  20. int main() {
  21. #ifdef Dmaxiya
  22. freopen("test.txt", "r", stdin);
  23. #endif // Dmaxiya
  24. ios::sync_with_stdio(false);
  25. fac[0] = 1;
  26. for(int i = 1; i < maxn; ++i) {
  27. fac[i] = fac[i - 1] * i;
  28. }
  29. while(scanf("%d%d", &A, &B) != EOF) {
  30. printf("%I64d\n", fac[min(A, B)]);
  31. }
  32. return 0;
  33. }

B. Crossword solving

题意

给定两个字符串 ,可以将字符串 任意位置上的字符改为 '?',使 能够匹配 的某个子串,在匹配过程中, 串中的 '?' 可以匹配任意字符,问最少需要修改多少个字符为 '?' 才能使得 可以匹配 的某个子串。

输入

第一行包含两个整数 ,分别表示字符串 的长度,第二行为字符串 ,第三行为字符串 ,字符串只包含小写字母。

输出

第一行为一个整数 ,表示最少需要修改的字符数,第二行为 个整数,每个整数表示需要修改的字符在 中的位置。如果有多解输出任意一组。

样例

输入 输出
3 5
abc
xaybz
2
2 3
4 10
abcd
ebceabazcd
1
2

题解

对于 的每个长度为 的子串计算与 串的不同字符数的最小值,并将不同字符的位置记录下来,就是答案。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  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 <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 1000 + 100;
  18. int n, m, ans;
  19. char s[maxn], t[maxn];
  20. bool vis[maxn], visans[maxn];
  21. int main() {
  22. #ifdef Dmaxiya
  23. freopen("test.txt", "r", stdin);
  24. #endif // Dmaxiya
  25. ios::sync_with_stdio(false);
  26. while(scanf("%d%d", &n, &m) != EOF) {
  27. ans = n;
  28. for(int i = 1; i <= n; ++i) {
  29. visans[i] = true;
  30. }
  31. scanf("%s%s", s + 1, t + 1);
  32. for(int i = 1; i <= m - n + 1; ++i) {
  33. int tmp = 0;
  34. memset(vis, 0, sizeof(vis));
  35. for(int j = 0; j < n; ++j) {
  36. if(s[j + 1] != t[i + j]) {
  37. vis[j + 1] = true;
  38. ++tmp;
  39. }
  40. }
  41. if(tmp < ans) {
  42. ans = tmp;
  43. memcpy(visans, vis, sizeof(vis));
  44. }
  45. }
  46. bool flag = false;
  47. printf("%d\n", ans);
  48. for(int i = 1; i <= n; ++i) {
  49. if(visans[i]) {
  50. if(flag) {
  51. printf(" ");
  52. }
  53. printf("%d", i);
  54. flag = true;
  55. }
  56. }
  57. printf("\n");
  58. }
  59. return 0;
  60. }

C. Hacker, pack your bags!

题意

的老板给她放了 天的假,她从旅行社那里拿到了所有的行程表以及花费 ,分别表示第 个行程从第 天出发,第 天回来,需要花费 元,期间经过 天。 想要挑选两次不相交的行程,且这两次行程总的旅行天数和正好为 天,两段行程不相交等价于 或者 ,问在满足以上条件的情况下的最小花费。

输入

第一行包含两个整数 ,接下去 行每行三个整数

输出

如果无法找到两个不相交且天数和等于 的行程,则输出 ,否则输出最小花费。

样例

输入 输出 提示
4 5
1 3 4
1 2 5
5 6 1
1 2 4
5 应该选择第 个和第 个行程,这样行程的总天数等于
,且总花费为
3 2
4 6 3
2 4 1
3 5 4
-1 每一个行程的区间长度都为 ,所以无法找到合适的旅行方案。

题解

先将所有行程按左端点排序,枚举每一个行程 ,将所有满足 的行程记录下来,记录第 个行程的天数所对应的最小花费,就可以 地查询出 对应的天数的最小花费,对每一个行程取最小值就是答案。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  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 <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 200000 + 100;
  18. struct Node {
  19. int l, r;
  20. LL cost;
  21. };
  22. bool operator<(const Node &a, const Node &b) {
  23. return a.l < b.l;
  24. }
  25. bool cmp(const Node &a, const Node &b) {
  26. return a.r < b.r;
  27. }
  28. int n, x, day;
  29. LL ans;
  30. LL cost[maxn];
  31. Node node[maxn], ntmp[maxn];
  32. int main() {
  33. #ifdef Dmaxiya
  34. freopen("test.txt", "r", stdin);
  35. #endif // Dmaxiya
  36. ios::sync_with_stdio(false);
  37. while(scanf("%d%d", &n, &x) != EOF) {
  38. ans = INT_MAX;
  39. memset(cost, 0x3f, sizeof(cost));
  40. for(int i = 0; i < n; ++i) {
  41. scanf("%d%d%I64d", &node[i].l, &node[i].r, &node[i].cost);
  42. ntmp[i] = node[i];
  43. }
  44. sort(node, node + n);
  45. sort(ntmp, ntmp + n, cmp);
  46. int Index = 0;
  47. for(int i = 0; i < n; ++i) {
  48. while(ntmp[Index].r < node[i].l) {
  49. day = ntmp[Index].r - ntmp[Index].l + 1;
  50. cost[day] = min(cost[day], ntmp[Index].cost);
  51. ++Index;
  52. }
  53. day = node[i].r - node[i].l + 1;
  54. if(day >= x) {
  55. continue;
  56. }
  57. ans = min(ans, node[i].cost + cost[x - day]);
  58. }
  59. if(ans == INT_MAX) {
  60. printf("-1\n");
  61. } else {
  62. printf("%I64d\n", ans);
  63. }
  64. }
  65. return 0;
  66. }

D. My pretty girl Noora

题意

在一次选美大赛中,有 个小姐姐参加比赛,比赛规则为:将 个小姐姐分到各个组里,每组 人,在每组之间先两两进行比较选出小组的优胜者,每组内的比较次数为 ,其中的 名优胜者继续分组比赛,直到产生最后的优胜者。
为当比赛人数为 时最小的比较次数,要求计算 取模的结果。

输入

输入包含三个整数

输出

输出答案。

样例

输入 输出 提示
2 2 4 19 显然 ,而对于 ,如果有 个选手参赛,可以将她们分为两组,
每组两人,则组内比较次数为 ,第一轮需要比较 次,第二轮为每组的优胜者(共 人),
经过 次比较可以得出优胜者;也可以将 个人直接分到同一组,那么总的比较次数为
次,因此最小的比较次数为 ,所以 ,代入公式可以计算出答案为

题解

由题可知,组内比较次数随着组内人数的增加平方级地增长,所以应该将每一轮的分组尽可能地多,每组人数尽可能少,才能使 最优,如果 为质数,则 ,否则 ,其中 的最小的质因数,公式的其他部分直接 求解即可。

过题代码

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cmath>
  5. #include <sstream>
  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 <algorithm>
  15. using namespace std;
  16. #define LL long long
  17. const int maxn = 5000000 + 100;
  18. const LL MOD = 1000000000 + 7;
  19. int cnt;
  20. LL t, l, r;
  21. LL f[maxn], prime[maxn];
  22. bool vis[maxn];
  23. void Prime() {
  24. cnt = 0;
  25. for(LL i = 2; i < maxn; ++i) {
  26. if(!vis[i]) {
  27. prime[cnt++] = i;
  28. }
  29. for(LL j = 0; j < cnt && i * prime[j] < maxn; ++j) {
  30. LL k = i * prime[j];
  31. vis[k] = true;
  32. if(i % prime[j] == 0) {
  33. break;
  34. }
  35. }
  36. }
  37. }
  38. LL get(LL x) {
  39. if(!vis[x]) {
  40. return x * (x - 1) / 2;
  41. }
  42. LL ret = 0;
  43. for(int i = 0; prime[i] * prime[i] <= x; ++i) {
  44. if(x % prime[i] == 0) {
  45. ret = f[prime[i]] * (x / prime[i]);
  46. x /= prime[i];
  47. break;
  48. }
  49. }
  50. ret %= MOD;
  51. ret += f[x];
  52. return ret;
  53. }
  54. int main() {
  55. #ifdef Dmaxiya
  56. freopen("test.txt", "r", stdin);
  57. #endif // Dmaxiya
  58. ios::sync_with_stdio(false);
  59. Prime();
  60. for(int i = 2; i < maxn; ++i) {
  61. f[i] = get(i) % MOD;
  62. }
  63. while(scanf("%I64d%I64d%I64d", &t, &l, &r) != EOF) {
  64. LL ans = 0;
  65. LL tt = 1;
  66. for(LL i = l; i <= r; ++i) {
  67. ans = (ans + (tt * f[i]) % MOD) % MOD;
  68. tt = (tt * t) % MOD;
  69. }
  70. printf("%I64d\n", ans);
  71. }
  72. return 0;
  73. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注