[关闭]
@Dmaxiya 2025-12-19T10:01:21.000000Z 字数 3482 阅读 26

Hello World 2024 蓝桥杯选拔赛题解

Hello_World


T550164 HelloWorld的变迁

给出一个数字 ,如果 的末尾的值四位大于等于 ,则输出 ,否则输出 HelloWorld

注意到 的最大值为 ,远大于 int 所能表示的上限,所以我们需要使用 long long 来读入数字。

取末尾四位只需要将 10000 取余数即可。

AC 代码示例

T550165 新的风暴已经出现

给出 个数,求出 个数两两相乘的总和。

运用乘法分配律可以将等式转换为

所以只需要设置两个变量, 表示之前所有数字的和, 表示当前计算的答案,累加之后即可。

注意答案会超过 int 上限,需要使用 long long

AC 代码示例

T550173 水群高手小hi

数字位数少于 的数必然小于 ,此时的答案一共有 个,位数等于 时,至少有 个自然数满足答案,其中 的最高位,最后特判 是否满足题意即可。

AC 代码示例

T550171 简单的题目

序列满足如下递推式:

输入 ,输出

50% 分数解法

按题目描述正确计算即可,不会爆 int,轻松拿下 50%,核心代码如下:

  1. for (int i = 1; i <= n; ++i) {
  2. if (a % 2 == 0) {
  3. a /= 2;
  4. } else {
  5. a = a * 3 + 1;
  6. }
  7. }

100% 分数解法

通过手推可以发现,似乎最终总是会回到 的循环上,可以手写代码从 验证都能满足这个规律,所以可以先跑 次,如果 次跑完还没有到 ,就使用 次后 的值,如果在 次内先到达了 ,就计算 与当前次数的差值,对周期 取余可以快速得到结果(你是否在找:考拉兹猜想,冰雹猜想)。

注意 时永远为

AC 代码示例

数据生成

点击链接查看随机数据生成代码,其中 std.exe 为标程 exe 文件。

T550172 lhx牌碰碰车

给出 个数,现在要将 个数划分成两个集合,目标是让两个集合的和的最大值最小,输出大的集合的总和。

经典的动态规划问题。

开一个数组 f[i]f[i] 时表示总和为 的集合存在。我们考虑新放入一个数 ,当前所有的方案都能将这个数加入,如果大小为 的方案存在,那么加入这个数之后大小为 的方案也存在。同时还可以不使用这个数,所以原先的方案同样存在,将两种情况合并即为最终答案。

将所有数加入之后,找到总和离 最近的 f[i] 即为答案。

AC 代码示例

T550170 数学天才再临

题意:在 的范围内等概率地取 个正整数,求 个正整数两两互质的方案数。

(比赛无聊的时候,看了题面里链接的视频了吗,非常有意思,强烈推荐!)

解法

时只有一种填法:每一位都填 ,必然满足两两互质,因此直接输出 可以得到 的分数。

解法

时,其中一种填法是所有位都填 ,另一种是从 位中选择一个填 (共 个可选位置),因此当 时可以直接输出

解法

时两个 for 循环 枚举两个数字,当最大公约数为 时加到答案上,核心代码如下:

  1. int gcd(int a, int b) {
  2. return b == 0? a: gcd(b, a % b);
  3. }
  4. for (int i = 1; i <= m; ++i) {
  5. for (int j = 1; j <= m; ++j) {
  6. if (gcd(i, j) == 1) {
  7. ++ans;
  8. }
  9. }
  10. }

解法

每一位都枚举 ,枚举到第 个数字时判断是否与前 个数字都互质,若都互质则填入,继续枚举第 个数字。

由于循环层数 非固定值,可用递归实现暴力搜索,不会写递归可以通过对 值的特判写几个分支,分别对应不同层数的 for 循环,时间复杂度 ,核心代码如下:

  1. int gcd(int a, int b) {
  2. return b == 0? a: gcd(b, a % b);
  3. }
  4. void dfs(int depth) {
  5. if (depth == n + 1) {
  6. ++ans;
  7. return ;
  8. }
  9. for (int i = 1; i <= m; ++i) {
  10. bool flag = true;
  11. for (int j = 1; j < depth; ++j) {
  12. if (gcd(i, num[j]) != 1) {
  13. flag = false;
  14. break;
  15. }
  16. }
  17. if (flag) {
  18. num[depth] = i;
  19. dfs(depth + 1);
  20. }
  21. }
  22. }

解法

换一种角度考虑”互质“:一个整数可以分解成多个质因数幂次相乘的形式,当两个整数的质因数没有交集时,这两个数字互质。

用二进制位表示质因数集合,第 位为 表示包含第 个质数 ,第 位为 表示包含第二个质数 ,以此类推。

定义状态 表示前 个已填数字的质因数集合的二进制表示为 ,有如下递推式:

其中, 表示按位异或, 表示按位与, 表示整数 的质因数集合的二进制位表示,如 ,上式在 的质因数集合为 所代表集合的子集时(即满足条件 )可以转移。

递推式含义为:前 位质因数状态为 的方案数,等于往第 位填数字 的方案数总和,当第 位填入 时,前 位的质因数状态只能为 才能保证前 位整数两两互质。初始值为 ,答案为 为小于等于 的质数个数。

时间复杂度:递推式时间复杂度为 以内有 个质数,最坏情况下计算次数为 ,可以通过这部分数据, 时最坏情况计算次数为 ,超过 会导致超时。

点击链接获取对应代码。

满分解法

继续观察发现,当我们找到一组不等于 的由 个数字组成的互质组合时(如 ),我们有 种方式把它放到一个长度为 的数组,其他 位可以全填 ,发现这里面的方案数计算时间复杂度与 无关( 可以 预处理, 读取)。

因此我们可以定义状态 表示由 不包含 已填数字的质因数集合的二进制表示为 ,有如下递推式:

递推式与上一种解法类似,但 开始,且 最大为 ,最终答案等于:

其中 为小于等于 的质数的个数,表示最多只需要 位就能枚举尽所有方案,初始状态

时间复杂度:,其中 为预处理 的时间复杂度,当 时,最多需要执行 ,加上一些小优化(见代码)可通过本题 100% 数据。

AC 代码示例

附加题

  1. ,如何求解?(提示:欧拉函数)
  2. ,如何求解?(提示:质数的性质)

数据生成

点击链接获取随机数据生成代码,其中 std.exe 为标程 exe 文件。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注