当前位置: 首页 > ds >正文

CSP 2024 提高级第一轮(CSP-S 2024)阅读程序第一题解析

阅读程序第一题解析

#include <iostream>
using namespace std;const int N = 1000;
int c[N];int logic(int x, int y) {return (x & y) ^ ((x ^ y) | (~x & y));
}void generate(int a, int b, int *c) {for (int i = 0; i < b; i++)c[i] = logic(a, i) % (b + 1);
}void recursion(int depth, int *arr, int size) {if (depth <= 0 || size <= 1) return;int pivot = arr[0];int i = 0, j = size - 1;while (i <= j) {while (arr[i] < pivot) i++;while (arr[j] > pivot) j--;if (i <= j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;i++; j--;}}recursion(depth - 1, arr, j + 1);recursion(depth - 1, arr + i, size - i);
}int main() {int a, b, d;cin >> a >> b >> d;generate(a, b, c);recursion(d, c, b);for (int i = 0; i < b; ++i) cout << c[i] << " ";cout << endl;
}

程序分析

logic函数

int logic(int x, int y) {return (x & y) ^ ((x ^ y) | (~x & y));
}

我们列举一些x和y,发现(x & y) ^ ((x ^ y) | (~x & y))等同于x | y

xy(x & y) ^ ((x ^ y) | (~x & y))x | y
0333
0777
0888
1777
2133

用C++证明:

generate函数

void generate(int a, int b, int *c) {for (int i = 0; i < b; i++)c[i] = logic(a, i) % (b + 1);
}

函数行为:

  • 传入a,b(确保 c[i] 的值在 [0, b] 范围内),c数组。
  • 循环,从0到b。
    • a | i % (b + 1) 赋值给c[i]。

recursion函数

void recursion(int depth, int *arr, int size) {if (depth <= 0 || size <= 1) return;int pivot = arr[0];int i = 0, j = size - 1;while (i <= j) {while (arr[i] < pivot) i++;while (arr[j] > pivot) j--;if (i <= j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;i++; j--;}}recursion(depth - 1, arr, j + 1);recursion(depth - 1, arr + i, size - i);
}

recursion函数是一个带深度限制的快速排序的实现,排完序后数组不完全有序。(快速排序运用了分治的思想,每次找到一个任意下标的数,将小于该数的数放于左边,大于该数的数放于右边)。

判断题

  1. 当1000≥d≥b 时,输出的序列是有序的。(正确)
    解析:最坏情况下,快速排序的递归深度可能达到 b(退化为 O(n2))。
    但题目保证 d≥b,因此 递归不会提前终止,最终数组会被完全排序。
  2. 当输入 5 5 1 时,输出为 1 1 5 5 5。(错误)
    解析:
    generate(a = 5, b = 5, c):
    c[i] = (5 | i) % 6
i5 | i(二进制)5 | i(十进制)c[i] = (5 | i) % 6
0101 | 000 = 10155 % 6 = 5
1101 | 001 = 10155 % 6 = 5
2101 | 010 = 11177 % 6 = 1
3101 | 011 = 11177 % 6 = 1
4101 | 100 = 10155 % 6 = 5

c = {5, 5, 1, 1, 5}
recursion():

来自DeepSeek的《睿智》
第1层递归(d=1):
基准值 pivot = c[0] = 5。
分区过程:
i=0,j=4:
c[0]=5(>=5,不移动 i)
c[4]=5(<=5,不移动 j)
交换 c[0] 和 c[4](数组不变,仍为 [5, 5, 1, 1, 5])
i++ → i=1,j-- → j=3
i=1,j=3:
c[1]=5(>=5,不移动 i)
c[3]=1(<=5,不移动 j)
交换 c[1] 和 c[3] → 数组变为 [5, 1, 1, 5, 5]
i++ → i=2,j-- → j=2
i=2,j=2:
c[2]=1(<5,i++ → i=3)
c[2]=1(<=5,不移动 j)
循环终止(i > j)
分区结果:
左子数组:[5, 1, 1](j + 1 = 3)
右子数组:[5, 5](arr + i = c + 3,size - i = 2)
递归深度 d=0,不再继续递归。

  1. 假设数组 c 长度无限制,该程序所实现的算法的时间复杂度是 O(b) 的。(错误)
    解析:recursion()函数的复杂度不是O(b),若不考虑深度限制,平均复杂度是O(b log b)。

选择题

  1. 函数 int logic(int x, int y) 的功能是(B)
    A. 按位与
    B. 按位或
    C. 按位异或
    D. 以上都不是
    解析:我们列举一些x和y,发现(x & y) ^ ((x ^ y) | (~x & y))等同于x | y:
xy(x & y) ^ ((x ^ y) | (~x & y))x | y
0333
0777
0888
1777
2133
  1. 当输入为 10 100 100 时,输出的第 100 个数是?(C)
    A. 91
    B. 94
    C. 95
    D. 98
    解析:最坏情况下,快速排序需要n - 1重递归,而100 > 100 - 1,所以函数执行完毕c数组已经有序,答案就是(10 | i) % 101 i ∈ [0, 99]的最大值。
    10的二进制形式为:1010,所以与10相或必定第一位和第三位为1(从右起)。
十进制二进制
1001100100
991100011
981100010
971100001
961100000
951011111

95的第一位和第三位为1(从右起),所以选C。

http://www.xdnf.cn/news/9622.html

相关文章:

  • 【Docker】技术架构演进
  • failed to bind host port for 0.0.0.0:3306
  • 【 Docker系列】 Docker部署kafka
  • 办公效率王Word批量转PDF 50 +文档一键转换保留原格式零错乱
  • GC1267F单相全波风扇电机预驱动器芯片详解
  • 精益数据分析(93/126):增长率的真相——从数据基准到科学增长策略
  • Linux 中常见的安全与权限机制
  • Vim常用快捷键
  • element-plus主题换色
  • React-native的新架构
  • unity一个箭矢的轨迹
  • 湖北理元理律师事务所:债务优化中的“生活锚点”设计
  • AI 让无人机跟踪更精准——从视觉感知到智能预测
  • HTML实战:响应式个人资料页面
  • 每日Prompt:心中的佛
  • 操作系统学习(一)——操作系统基础
  • 数据库管理与高可用-MySQL数据库操作
  • Prometheus学习之pushgateway和altermanager组件
  • Linux的SHELL脚本基础
  • docker-记录一次容器日志<container_id>-json.log超大问题的处理
  • opencv + jpeg_turbo(启用SIMD加速)
  • Flutter3.22适配运行鸿蒙系统问题记录
  • 算力卡上部署OCR文本识别服务与测试
  • w~视觉~合集6
  • 【组件】跳动的图标 动画
  • 实验设计与分析(第6版,Montgomery)第4章随机化区组,拉丁方, 及有关设计4.5节思考题4.1~4.4 R语言解题
  • GRIT:让AI“指着图说话“的新思路
  • get_rga_thread线程和low_camera_venc_thread线程获取低分辨率VENC码流数据
  • ORB-SLAM2学习笔记:ComputeKeyPointsOctTree分析过程记录
  • 【C语言】详解 指针