[关闭]
@Dmaxiya 2018-08-17T10:27:50.000000Z 字数 5086 阅读 1008

Codeforces Round #309 (Div. 2)

Codeforces


Contests 链接:Codeforces Round #309 (Div. 2)
过题数:3
排名:143/9399

A. Kyoya and Photobooks

题意

给定一个由小写字母组成的字符串 ,可以在字符串的任意位置插入一个字符,从而生成一个新的字符串,问能够生成的不同的新字符串的个数。

数据范围

题解

在字符串的每个位置暴力插入,放入 中统计即可。

过题代码

  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. string str;
  21. set<string> st;
  22. int main() {
  23. #ifdef LOCAL
  24. freopen("test.txt", "r", stdin);
  25. // freopen("test1.out", "w", stdout);
  26. #endif // LOCAL
  27. ios::sync_with_stdio(false);
  28. while(cin >> str) {
  29. st.clear();
  30. int len = str.length();
  31. for(int i = 0; i <= len; ++i) {
  32. for(char ch = 'a'; ch <= 'z'; ++ch) {
  33. st.insert(str.substr(0, i) + ch + str.substr(i, len - i));
  34. }
  35. }
  36. cout << st.size() << endl;
  37. }
  38. return 0;
  39. }

B. Ohana Cleans Up

题意

给定一个 矩阵,每次操作可以将任意一列的所有 翻转为 翻转为 ,问最多可以使多少行变为全

数据范围

题解

由于每次翻转是按列翻转,所以对于一种固定的列的翻转,要使 行变为全 ,这 行的 位置必须完全相同,即这些串必须相等,所以用 统计每种字符串的个数,求最大的字符串出现个数就是答案。

过题代码

  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, ans;
  21. string str;
  22. map<string, int> mp;
  23. int main() {
  24. #ifdef LOCAL
  25. freopen("test.txt", "r", stdin);
  26. // freopen("test1.out", "w", stdout);
  27. #endif // LOCAL
  28. ios::sync_with_stdio(false);
  29. while(cin >> n) {
  30. mp.clear();
  31. ans = 0;
  32. for(int i = 0; i < n; ++i) {
  33. cin >> str;
  34. ++mp[str];
  35. ans = max(ans, (int)mp[str]);
  36. }
  37. cout << ans << endl;
  38. }
  39. return 0;
  40. }

C. Kyoya and Colored Balls

题意

个球,每个球有一种颜色,总共有 种颜色,颜色编号为 ,第 种颜色的球的个数为 。现在 将这些球都放入袋子中,依次从袋子中抽球,问第 种颜色的最后一个抽出来的球,比第 种颜色的最后一个被抽出的球早抽出的总的方案数有多少种,输出方案对 取模后的结果。

数据范围

题解

题目要算的其实是排列的方案数,我们可以通过这种方式生成合法的排列:将第 到第 种颜色的球依次放入排列中,在放第 种颜色的球时,先将一个球放在最后的位置,剩下的 个球就可以任意插入到前 个球的排列中,这就相当于计算在 个球中插入 个隔板的方案数,方案数为:

过题代码

  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 LL MOD = 1000000007;
  21. const int maxn = 1000000 + 100;
  22. int n;
  23. LL fac[maxn];
  24. LL num[maxn], sum[maxn];
  25. void exgcd(LL a, LL b, LL &d, LL &x, LL &y) {
  26. if(b == 0) {
  27. d = a;
  28. x = 1;
  29. y = 0;
  30. } else {
  31. exgcd(b, a % b, d, y, x);
  32. y -= x * (a / b);
  33. }
  34. }
  35. LL inv(LL n) {
  36. LL x, y, d;
  37. exgcd(n, MOD, d, x, y);
  38. x = (x % MOD + MOD) % MOD;
  39. return x;
  40. }
  41. int main() {
  42. #ifdef LOCAL
  43. freopen("test.txt", "r", stdin);
  44. // freopen("test1.out", "w", stdout);
  45. #endif // LOCAL
  46. ios::sync_with_stdio(false);
  47. fac[0] = 1;
  48. for(int i = 1; i < maxn; ++i) {
  49. fac[i] = fac[i - 1] * i % MOD;
  50. }
  51. while(scanf("%d", &n) != EOF) {
  52. for(int i = 1; i <= n; ++i) {
  53. scanf("%I64d", &num[i]);
  54. sum[i] = sum[i - 1] + num[i];
  55. }
  56. LL ans = 1;
  57. for(int i = 1; i <= n; ++i) {
  58. ans = ((ans * (fac[sum[i] - 1] * inv(fac[sum[i - 1]]) % MOD) % MOD) * inv(fac[num[i] - 1])) % MOD;
  59. }
  60. printf("%I64d\n", ans);
  61. }
  62. return 0;
  63. }

D. String Game

题意

对于一个给定的 的排列,可以通过值 下标找到许多个环,例如:序列 ,可以找到环 ,在每个环内,将数字按从大到小排序,再以每个环为整体,按字典序排序,可以得到:,得到新的序列 ,对于某些特殊的序列,通过这样的变换后仍是它自己。给定 ,找到 的全排列中,满足以上关系的第 小的排列。

数据范围

,其中 表示所有满足条件的排列数。

题解

首先通过打一个 的表可以找到以下满足条件的排列:


可以发现,这些满足条件的排列,相比于排列 只有相邻两个数字之间存在交换,我们将交换的两个数字标为 ,其他位标为 ,可以产生下面的序列:

箭头右边的数字表示交换位置的数字的最高位(假设右边为最低位,且下标从 开始),可以发现,数字 对应的序列的最高两位都为 ,最低两位与数字 对应的序列的最低两位相同,数字 对应的序列的最高两位都为 ,最低三位与数字 对应的序列的最低三位相同,再往后推(将 扩大到 或者更大)可以发现,数字 对应的序列的最高两位总是 ,最低 位与数字 对应的序列的最低 位相同,如果我们将 记为数字 对应的序列个数,令 ,则 ,这正好是一个斐波那契数列,因此可以对斐波那契数列进行二分查找,找到需要交换的最高位的位置,交换后将 减去 ,继续二分查找,直到

过题代码

  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. typedef long long LL;
  20. const int maxn = 100 + 100;
  21. int n, cnt;
  22. LL k;
  23. int ans[maxn];
  24. LL fib[maxn];
  25. LL *it;
  26. int main() {
  27. #ifdef LOCAL
  28. freopen("test.txt", "r", stdin);
  29. // freopen("test1.out", "w", stdout);
  30. #endif // LOCAL
  31. ios::sync_with_stdio(false);
  32. fib[0] = 1;
  33. fib[1] = 1;
  34. for(int i = 2; i < maxn; ++i) {
  35. fib[i] = fib[i - 1] + fib[i - 2];
  36. if(fib[i] > 1000000000000000000LL) {
  37. cnt = i;
  38. break;
  39. }
  40. }
  41. while(scanf("%d%I64d", &n, &k) != EOF) {
  42. for(int i = 1; i <= n; ++i) {
  43. ans[i] = i;
  44. }
  45. while(k > 1) {
  46. it = lower_bound(fib, fib + cnt, k);
  47. int pos = n - (it - fib) + 1;
  48. swap(ans[pos], ans[pos + 1]);
  49. --it;
  50. k -= *it;
  51. }
  52. for(int i = 1; i <= n; ++i) {
  53. if(i != 1) {
  54. printf(" ");
  55. }
  56. printf("%d", ans[i]);
  57. }
  58. printf("\n");
  59. }
  60. return 0;
  61. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注