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

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。

相关文章:

  • Typora中文直装版
  • 2025.5.28总结
  • 2. 数据结构基本概念 (2)
  • Uniapp+UView+Uni-star打包小程序极简方案
  • 设计模式-装饰模式
  • Day05
  • 深度解析 Dockerfile 配置:构建高效轻量的FastAPI 应用镜像
  • Docker Desktop无法在windows低版本进行安装
  • JS逆向 QQ音乐sign签名|webpack实战 (上)
  • RocksDB
  • 对比RFX2401C:AT2401C功率放大器的性价比与PIN兼容方案
  • 2025年5月AI科技领域周报(5.19-5.25):大模型多模态突破 具身智能开启机器人新纪元
  • qt ubuntu 20.04 交叉编译
  • jq checked选中触发事件
  • 代码输出题:异步事件循环
  • 梯形面积计算shell脚本
  • Java设计模式之设计原则
  • 深入解析 Spring @Transactional 的事务开启机制
  • 【计算机网络】第1章:概述—分组延时、丢失和吞吐量
  • BugKu Web渗透之矛盾
  • 网站开发大牛/成都最新热门事件
  • 河南做网站哪个公司好/百度排名点击软件
  • 广州seo托管/seo优化技术厂家
  • 如何查看vs中建设好的网站/原创软文
  • 网站策划工作条件/上海网站seo外包
  • 网站制作流程 优帮云/天津百度seo