这次的题思维都很强,等之后的考试结束会集中精力重新训练一些思维题。

A - A simple question

CodeForces - 520B

思路:

直接看的话,很容易发现如果 \(n >= m\) 的话 \(sum = n - m\) 即可,但反过来其实 \(m\) 推导 \(n\) 更简单(WA几发后才发现。。)

如果 \(m\) 为偶数的话 缩小一半,不然的话先变为偶数再除以2。这样一定能变为 \(n\)

  1. void solve() {
  2. int n, m;
  3. cin >> n >> m;
  4. int sum = 0;
  5. if (n >= m)
  6. sum = n - m;
  7. else {
  8. while (n != m) {
  9. if (m % 2 == 0 && m > n)
  10. m = m / 2, sum++;
  11. else if (n >= m) {
  12. sum = sum + n - m;
  13. break;
  14. }
  15. if (m % 2 != 0 && m > n)
  16. m = (m + 1) / 2, sum = sum + 2;
  17. }
  18. }
  19. cout << sum << endl;
  20. }

B - Game

Gym - 102822G (出处2020 CCPC绵阳站)

题解思路参考:

看起来是博弈对吧?对,的确是使用SG函数,但蒟蒻表示不会,只能一个个模拟情况,赛后看了下这道题的官方题解(没想到也还是一道模拟找规律的题2333)

官方题解截图

  1. // 这里用的是解法二
  2. #include <bits/stdc++.h>
  3. using namespace std;
  4. typedef long long ll;
  5. ll c0, c1, c2, c3;
  6. int Case = 1;
  7. int check() {
  8. if (c0 == 0 && c1 == c0 && c2 == 0 && c3 == 0)
  9. return 0;
  10. int f = 1;
  11. if (c3 == 0) {
  12. if (c1 == 0 && c2 == 0) {
  13. if (c0 == 0 || c0 % 2)
  14. f = 0;
  15. } else {
  16. if (c0 % 2 == 0) {
  17. if (c1 % 3 == 0)
  18. f = 0;
  19. else {
  20. if (c1 % 3 == 1 && c2 == 0)
  21. f = 0;
  22. }
  23. } else {
  24. if (c1 % 3 == 1 && c2 > 0)
  25. f = 0;
  26. else if (c1 % 3 == 2 && c2 <= 1)
  27. f = 0;
  28. }
  29. }
  30. } else {
  31. if (c0 % 2 == 0) {
  32. if (c1 % 3 == 0)
  33. f = 0;
  34. else if (c1 % 3 == 1 && c2 == 0)
  35. f = 0;
  36. } else {
  37. if (c1 % 3 == 1 && c2 > 0)
  38. f = 0;
  39. else if (c1 % 3 == 2 && c2 <= 1)
  40. f = 0;
  41. }
  42. }
  43. return f;
  44. }
  45. void solve() {
  46. cin >> c0 >> c1 >> c2 >> c3;
  47. int Win_one = check();
  48. cout << "Case #" << Case++ << ": ";
  49. if (Win_one == 1)
  50. cout << "Rabbit\n";
  51. else
  52. cout << "Horse\n";
  53. }
  54. int main() {
  55. // freopen("in.txt", "r", stdin);
  56. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  57. int _;
  58. cin >> _;
  59. while (_--)
  60. solve();
  61. }

看博客的时候发现有人用DFS写了下,感觉也行。下面贴代码

Code
  1. int dfs(int c0, int c1, int c2, int c3) {
  2. if (c0 == 0 && c1 == 0)
  3. return 0;
  4. if (c0 == 0 && c2 == 0 && c1 < 2)
  5. return 0;
  6. if (c0 > 0 && !dfs(c0 - 1, c1, c2, c3))
  7. return 1;
  8. if (c1 >= 2 && !dfs(c0, c1 - 2, c2 + 1, c3))
  9. return 1;
  10. if (c1 > 0 && c2 > 0 && !dfs(c0, c1 - 1, c2 - 1, c3 + 1))
  11. return 1;
  12. return 0;
  13. }
  14. int main() {
  15. int t;
  16. scanf("%d", &t);
  17. int cas = 0;
  18. while (t--) {
  19. int a, b, c, d;
  20. scanf("%d%d%d%d", &a, &b, &c, &d);
  21. int win = -1;
  22. if (b == 0 && c == 0 && d == 0) {
  23. if (a == 0)
  24. win = 0;
  25. else if (a & 1)
  26. win = 0;
  27. else
  28. win = 1;
  29. } else
  30. win = dfs(a % 2, b % 3, c, d);
  31. printf("Case #%d: %s\n", ++cas, win ? "Rabbit" : "Horse");
  32. }
  33. return 0;
  34. }

C - CCCCC

题目链接: Gym - 102798D (出处:2020 CCPC威阳站)

思路图来自南京大学题解 ↓(感谢分享)

题意:给定一个数 C(\(1 \sim 1e18\)),找到一组 \(a,b\) 使得 \(a + b = c\ 且\ abc\ 的素数因子要求 < C\) ,如果存在这样的 \(a,b\) 的话输出 yes,不然输出 no

其实上方的图片中提到的解决方法已经很好了,现在翻译一下 ↓

解决方法(翻译):

  • 如果 c 无平方因子,那么是不会存在任意一组 a,b的,即可以直接输出 no
  • 如果 c 包含平方因子,即 :$c = p^2q\ (p > 1) $ ,所以可以令 \(a = pq\) , \(b = p(p -1)q\) ,使得 \(a + b = c\) ,并且 \(rad(abc) = rad(p^4(p -1)q^3) \leq rad(p(p - 1)q) \leq p^2q = c\)

要检查是否有无平方,则要要检查 \(p^2\) 直到 \(√{3c}\) 到 \(\sqrt{c}\) 的平方整数

\(O(√3c)\)

  1. // Author : RioTian
  2. // Time : 20/12/09
  3. #include <bits/stdc++.h>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N = 1e7 + 10;
  7. ll _, c;
  8. int cnt, prime[N];
  9. bool st[N];
  10. // 线性筛筛素数
  11. void init(ll n) {
  12. for (int i = 2; i <= n; ++i) {
  13. if (!st[i])
  14. prime[++cnt] = i;
  15. for (int j = 1; prime[j] <= n / i; ++j) {
  16. st[i * prime[j]] = true;
  17. if (i % prime[j] == 0)
  18. break;
  19. }
  20. }
  21. }
  22. void solve() {
  23. cin >> c;
  24. bool f = false;
  25. for (int i = 1; i <= cnt && !f; ++i) {
  26. ll p = prime[i];
  27. int s = 0;
  28. if (c % p == 0)
  29. while (c % p == 0)
  30. c /= p, s++;
  31. if (s >= 2)
  32. f = true;
  33. }
  34. ll x = sqrt(c);
  35. if (c > 1 && 1ll * x * x == c)
  36. f = true;
  37. if (f)
  38. cout << "yes\n";
  39. else
  40. cout << "no\n";
  41. }
  42. int main() {
  43. freopen("in.txt", "r", stdin);
  44. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  45. init(N - 10);
  46. for (cin >> _; _; _--)
  47. solve();
  48. }

D - String

计蒜客 - T2652

头铁记:一看到字符串就想到然往字符串方向走,但没想到是类搜索 2333

这里贴下学长的思路(绝不是懒的打字)

  1. // Author : RioTian
  2. // Time : 20/12/09
  3. #include <bits/stdc++.h>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N = 1e5 + 10;
  7. const int mod = 20100403;
  8. ll qpow(ll a, ll b) {
  9. ll ans = 1;
  10. a %= mod;
  11. for (; b; a = a * a % mod, b >>= 1)
  12. if (b & 1)
  13. ans = ans * a % mod;
  14. return ans;
  15. }
  16. ll C(ll n, ll m) {
  17. ll x = 1, y = 1;
  18. for (int i = 1; i <= m; ++i) {
  19. x = x * (n - i + 1) % mod;
  20. y = y * i % mod;
  21. }
  22. return x * qpow(y, mod - 2) % mod;
  23. }
  24. int main() {
  25. // freopen("in.txt", "r", stdin);
  26. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  27. ll n, m;
  28. cin >> n >> m;
  29. cout << (C(m + n, m) - C(m + n, m - 1) % mod + mod) % mod;
  30. }

E - Probability

AtCoder - abc184_d

题意:一个包里包含 X 个金币、Y 个银币、Z 个铜币。在包里钱币满足相 同颜色达到 100 之前,我们可以重复以下动作:随机选一种钱币,取出一枚, 再放入相同颜色钱币两枚。找出完成这些操作的期望值。

根据题目的意思,其实就是每次向包里随机加入一枚钱币,直到包里某种钱币数量达到 100。本题的核心是如何计算期望。本题属于标准的动态规划求期望问题。直接套用模板即可。

一道”简单“概率DP题,没怎么了解概率DP导致做不出

先贴一下学长给的概率DP知识点博客:Here

当理解基础的知识以后发现的确比较简单

DP 数组定义

定义 DP[i][j][k],表示有 i 枚金币, j 枚银币, k 枚铜币的期望。

初值

所有的期望都为零。

递推方法

使用逆推。

状态转移方程:

\[s = X + Y + Z\\
dp(i,j,k) = \frac{i}{s}*(dp(i + 1,j,k) + 1) + \frac{j}{s}*dp(i,j + 1,k) + 1) \\+ \frac{j}{s}*dp(i,j,k + 1) + 1))
\]

AC代码:

  1. // Author : RioTian
  2. // Time : 20/12/09
  3. #include <bits/stdc++.h>
  4. using namespace std;
  5. typedef long long ll;
  6. const int N = 1e2 + 10;
  7. double dp[N][N][N];
  8. int main() {
  9. // freopen("in.txt", "r", stdin);
  10. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  11. int a, b, c;
  12. cin >> a >> b >> c;
  13. for (int i = 99; i >= a; i--)
  14. for (int j = 99; j >= b; j--)
  15. for (int k = 99; k >= c; k--) {
  16. // 令 t = x + y + z,减少代码量
  17. double t = i + j + k;
  18. dp[i][j][k] = i / t * (dp[i + 1][j][k] + 1) +
  19. j / t * (dp[i][j + 1][k] + 1) +
  20. k / t * (dp[i][j][k + 1] + 1);
  21. }
  22. // 关于 C++ 的输出控制可以在我的以前博客找到
  23. cout << fixed << setprecision(9) << dp[a][b][c] << endl;
  24. }

时间和空间复杂度:

\(O(n^3)\)

学习的时候发现一种模拟方法:蒙特卡洛方法模拟

使用蒙特卡洛方法模拟

计划等有空好好学一下这个

本题核心其实是一个随机模拟过程,因此也可以使用蒙特卡洛方法(Monte Carlo method)来模拟这个过程。首先就不证明这个过程是收敛的,说真的,我也不大会证明,以后努力。具体的 Monte Carlo method 请看相关资料。

因此,我们只需要模拟这样的过程,只需要足够的样本数量就可以完成模拟。我这里用了 300 次就可以满足题目的需求。为什么 300 就够了,其实就是反复测试出来的。

AC代码

  1. // increment of coins
  2. // Using Monte Carlo method
  3. // Author : RioTian
  4. // Time : 20/12/09
  5. #include <bits/stdc++.h>
  6. using namespace std;
  7. typedef long long ll;
  8. const int N = 1e5 + 10;
  9. double prob(int n, int a, int b, int c) {
  10. int u = 100 - a;
  11. if (u > n)
  12. return 0.0;
  13. if (n - u > (99 - b) + (99 - c))
  14. return 0.0;
  15. double p = 1.0, ret = 0.0;
  16. for (int i = 0; i < u; i++)
  17. p *= 1.0 * (a + i) / (a + b + c + i);
  18. for (int v = 0; v <= n - u; ++v) {
  19. if (v + b > 99 || n - u - v + c > 99)
  20. continue;
  21. double exp = 1.0;
  22. for (int j = 0; j < v; j++)
  23. exp *= 1.0 * (b + j) / (a + b + c + u + j);
  24. for (int j = 0; j < n - u - v; j++)
  25. exp *= 1.0 * (c + j) / (a + b + c + u + v + j);
  26. for (int j = v; j >= 1; j--)
  27. exp *= 1.0 * (u - 1 + j) / j;
  28. for (int j = n - u - v; j >= 1; j--)
  29. exp *= 1.0 * (u - 1 + v + j) / j;
  30. ret += (p * exp);
  31. }
  32. return ret;
  33. }
  34. int main() {
  35. // freopen("in.txt", "r", stdin);
  36. ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
  37. int a, b, c;
  38. cin >> a >> b >> c;
  39. double ans = 0;
  40. for (int i = 1; i <= 300; ++i) {
  41. double pa = prob(i, a, b, c);
  42. double pb = prob(i, b, c, a);
  43. double pc = prob(i, c, a, b);
  44. ans += i * (pa + pb + pc);
  45. }
  46. cout << fixed << setprecision(9) << ans << endl;
  47. }

时间复杂度

\(O(n)\)。虽然也是三重循环,我们要注意到循环的次数是常数项。比如 main() 中的循环是固定 300 次,prob() 中的循环最多是 100 次。所以乘积还是常数次。

空间复杂度

\(O(n)\)

ACM训练赛:第20次的更多相关文章

  1. 山东省第三届ACM省赛

    Solved ID PID Title Accepted Submit   A 2407 Impasse (+) 0 0   B 2415 Chess 0 0   C 2414 An interest ...

  2. 第六届acm省赛总结(退役贴)

    前言: 这是我的退役贴,之前发到了空间里,突然想到也要在博客里发一篇,虽然我很弱,但是要离开了还是有些感触,写出来和大家分享一下,希望不要见笑.回来看看,这里也好久没有更新了,这一年确实有些懈怠,解题 ...

  3. 2014 ACM省赛总结

    今年ACM省赛已经过去一个星期左右了,2年的ACM训练是该做个总结了,因为前几日去參加蓝桥杯总决赛,所以没来的及写总结,如今在这小小总结一下吧-- 依晰记得去年省赛时候的样子,如今感觉那时像是个无知的 ...

  4. Contest1592 - 2018-2019赛季多校联合新生训练赛第二场(部分题解)

    Contest1592 - 2018-2019赛季多校联合新生训练赛第二场 D 10248 修建高楼(模拟优化) H 10252 组装玩具(贪心+二分) D 传送门 题干 题目描述 C 市有一条东西走 ...

  5. 记:青岛理工ACM交流赛筹备工作总结篇

    这几天筹备青岛理工ACM交流赛的过程中遇到了不少问题也涨了不少经验.对非常多事也有了和曾经不一样的看法, ​一直在想事后把这几天的流水帐记一遍,一直没空直到今天考完C++才坐下来開始动笔.将这几天的忙 ...

  6. 2014暑假ACM训练总结

    2014暑假ACM训练总结报告 匆匆之中,一个暑假又过去了,在学校训练的这段日子真的是感觉日子过得好快啊! 时光如箭,日月如梭! 匆忙的学习之中一个暑假就这样结束了,现在就来写一些总结吧,供自己以后阅 ...

  7. 计蒜客 ACM训练联盟周赛 第一场 从零开始的神棍之路 暴力dfs

    题目描述 ggwdwsbs最近被Zeratul和Kyurem拉入了日本麻将的坑.现在,ggwdwsbs有13张牌,Kyurem又打了一张,加起来有14张牌.ggwdwsbs想拜托你帮他判断一下,这14 ...

  8. 第九届蓝桥杯国赛+第二天的第11届acm省赛的总结

    第九届蓝桥杯国赛+第二天的第11届acm省赛的总结 25号坐的去北京的火车,10个小时的火车,然后挤了快两个小时的地铁,最终达到了中国矿业大学旁边的订的房间.12个小时很难受,晕车症状有点严重,吃了快 ...

  9. ACM省赛及蓝桥总结,且随疾风前行,身后亦须留心

    今年算是开始正式打比赛了,真正打起比赛来感觉的确是和平时训练不太一样,最重要的还是在心态和信心上. ACM省赛是拿下个银牌,昭哥上来就把K题金牌题给当签到题给签掉了,可惜我们没有利用好这一题.感觉第一 ...

随机推荐

  1. 在一个递增数组的rotate变换中找target

    Search in Rotated Sorted Array Suppose an array sorted in ascending order is rotated at some pivot u ...

  2. sql 训练及总结

    1.sql语句中=与in的区别,=是指一对一之间的等于,而in是指一对多之间的:同样的道理,<>与 not in的区别,<>是指一对一之间的不等于,而not  in是指一对多之 ...

  3. 虚拟机搭建CentOS 7系统

    准备工作先查看本机是否开启虚拟化 可以打开任务管理器中性能选项 可以看到虚拟化默认关闭,可通过打开BIOS,找到Configuration或Security选项,把Virtualization或者In ...

  4. C#高级编程之泛型一(泛型的引入、泛型的使用、何为泛型)

    为何引入泛型 当我们要对不同类型的参数执行类似的方法时:如下所示功能打印传入参数的相关信息. class CommonMethdod { /// <summary> /// show in ...

  5. C++ const的自我理解

    C++学习笔记–const const 是 constant 的缩写,本意是不变的,不易改变的意思.在 C++ 中是用来修饰内置类型变量,自定义对象,成员函数,返回值,函数参数. C++ const ...

  6. Caused by: java.lang.ClassNotFoundException: com.alibaba.druid.filter.logging.Log4j2Filter

    最开始遇到这个错误,百度,网上一堆的清一色解决方案,缺少log4j,引入log4j相关依赖,或者引入slf4j-over-log4j的依赖,但是好像都不行,最后还是谷歌靠谱,直接检索出github上的 ...

  7. webpack、node、npm关系

    webpack模块打包 webpack为了正常运行, 必须依赖node环境, node环境为了可以正常的执行很多代码,必须其中包含各种依赖的包 npm工具(node packages manager) ...

  8. python-网络安全编程第八天(实战高精度密码字典生成器)

    前言 emmmm 高精度密码字典源码 1.py import exrex import sys #url过滤处理 def host_para(host): if '://' in host: host ...

  9. RayFire的下载与安装方法

    RayFire的下载与安装方法 发布时间:2020/10/12 近几年,电影中融入了越来越多的动画元素,其中的爆炸场景更是十分吸引眼球.小编不禁好奇,什么样的插件能做出来如此好玩的特效,上网搜索一番发 ...

  10. python中正则表达式

    正则表达式是一种通用的字符串匹配技术,是不会因为编程语言不一样而发生变化的如果想查找对应规则的字符串,就可以用正则表达式python中要使用正则表达式需使用re模块,它是正则表达式在python中的封 ...