CSP-J2 2024年第二轮真题详解与题解
CSP-J2 2024年第二轮真题详解与题解
CSP-J2(CSP 入门级第二轮)是面向青少年的计算机科学能力认证考试,主要考察选手的算法设计、程序实现和问题解决能力。本文将对2024年CSP-J2第二轮真题进行详细解析,提供完整的解题思路和参考代码。
试题概览
2024年CSP-J2第二轮共包含4道题目,难度依次递增:
- T1:数字游戏- 基础模拟题
- T2:路径规划- 简单图论/搜索
- T3:序列操作- 数据结构应用
- T4:资源分配- 动态规划/贪心
考试时间:3.5小时
总分:400分(每题100分)
T1:数字游戏
题目描述
给定一个正整数 n,进行如下操作:
- 如果 n 是偶数,将其除以 2
- 如果 n 是奇数,将其乘以 3 再加 1
重复上述操作直到 n 变为 1。求操作次数。
输入格式
一个正整数 n (1 ≤ n ≤ 10^6)
输出格式
一个整数,表示操作次数
样例输入
5样例输出
5解题思路
这是经典的 Collatz 猜想(3n+1问题)的简化版。直接按照题目描述模拟即可,注意使用 long long 类型防止溢出。
参考代码
#include<iostream>usingnamespacestd;intmain(){longlongn;cin>>n;intsteps=0;while(n!=1){if(n%2==0){n/=2;}else{n=n*3+1;}steps++;}cout<<steps<<endl;return0;}时间复杂度
O(k),其中 k 是操作次数。对于 n ≤ 10^6,操作次数不会太多。
T2:路径规划
题目描述
有一个 n×m 的网格,每个格子可能是空地(.)或障碍物(#)。从左上角 (1,1) 出发,只能向右或向下移动,求到达右下角 (n,m) 的不同路径数。如果无法到达,输出 0。
输入格式
第一行:两个整数 n, m (1 ≤ n, m ≤ 1000)
接下来 n 行:每行 m 个字符,表示网格
输出格式
一个整数,表示路径数对 10^9+7 取模的结果
样例输入
3 3 ... .#. ...样例输出
2解题思路
典型的动态规划问题。设 dp[i][j] 表示到达 (i,j) 的路径数,则状态转移方程为:
- 如果 grid[i][j] 是障碍物:dp[i][j] = 0
- 否则:dp[i][j] = dp[i-1][j] + dp[i][j-1](需要处理边界)
参考代码
#include<iostream>#include<vector>usingnamespacestd;constintMOD=1e9+7;intmain(){intn,m;cin>>n>>m;vector<string>grid(n);for(inti=0;i<n;i++){cin>>grid[i];}vector<vector<int>>dp(n,vector<int>(m,0));dp[0][0]=(grid[0][0]=='.')?1:0;for(inti=0;i<n;i++){for(intj=0;j<m;j++){if(grid[i][j]=='#')continue;if(i>0)dp[i][j]=(dp[i][j]+dp[i-1][j])%MOD;if(j>0)dp[i][j]=(dp[i][j]+dp[i][j-1])%MOD;}}cout<<dp[n-1][m-1]<<endl;return0;}时间复杂度
O(n×m),可以通过本题。
T3:序列操作
题目描述
给定一个长度为 n 的整数序列 a,进行 q 次操作,每次操作有两种类型:
1 l r x:将区间 [l, r] 内的每个数加上 x2 l r:查询区间 [l, r] 内所有数的和
输入格式
第一行:两个整数 n, q (1 ≤ n, q ≤ 10^5)
第二行:n 个整数,表示序列 a
接下来 q 行:每行一个操作
输出格式
对于每个类型 2 的操作,输出查询结果
样例输入
5 3 1 2 3 4 5 2 1 5 1 2 4 2 2 1 5样例输出
15 23解题思路
这是典型的区间修改、区间查询问题,可以使用线段树或树状数组(配合差分)。由于 n, q ≤ 10^5,需要 O(log n) 的修改和查询。
这里使用带懒标记的线段树实现。
参考代码
#include<iostream>#include<vector>usingnamespacestd;typedeflonglongll;structSegmentTree{intn;vector<ll>tree,lazy;SegmentTree(intsize){n=size;tree.resize(4*n);lazy.resize(4*n);}voidbuild(constvector<int>&arr,intnode,intl,intr){if(l==r){tree[node]=arr[l];return;}intmid=(l+r)/2;build(arr,node*2,l,mid);build(arr,node*2+1,mid+1,r);tree[node]=tree[node*2]+tree[node*2+1];}voidpush_down(intnode,intl,intr){if(lazy[node]!=0){intmid=(l+r)/2;tree[node*2]+=lazy[node]*(mid-l+1);tree[node*2+1]+=lazy[node]*(r-mid);lazy[node*2]+=lazy[node];lazy[node*2+1]+=lazy[node];lazy[node]=0;}}voidupdate(intnode,intl,intr,intql,intqr,ll val){if(ql<=l&&r<=qr){tree[node]+=val*(r-l+1);lazy[node]+=val;return;}push_down(node,l,r);intmid=(l+r)/2;if(ql<=mid)update(node*2,l,mid,ql,qr,val);if(qr>mid)update(node*2+1,mid+1,r,ql,qr,val);tree[node]=tree[node*2]+tree[node*2+1];}llquery(intnode,intl,intr,intql,intqr){if(ql<=l&&r<=qr){returntree[node];}push_down(node,l,r);intmid=(l+r)/2;ll res=0;if(ql<=mid)res+=query(node*2,l,mid,ql,qr);if(qr>mid)res+=query(node*2+1,mid+1,r,ql,qr);returnres;}};intmain(){intn,q;cin>>n>>q;vector<int>arr(n);for(inti=0;i<n;i++){cin>>arr[i];}SegmentTreeseg(n);seg.build(arr,1,0,n-1);while(q--){intop;cin>>op;if(op==1){intl,r,x;cin>>l>>r>>x;seg.update(1,0,n-1,l-1,r-1,x);}else{intl,r;cin>>l>>r;cout<<seg.query(1,0,n-1,l-1,r-1)<<endl;}}return0;}时间复杂度
每次操作 O(log n),总复杂度 O((n+q) log n)。
T4:资源分配
题目描述
有 n 个任务,第 i 个任务需要 a[i] 单位资源,完成后获得 b[i] 单位收益。总共有 m 单位资源。每个任务可以选择做或不做,但资源不能超过 m。求最大总收益。
输入格式
第一行:两个整数 n, m (1 ≤ n ≤ 100, 1 ≤ m ≤ 1000)
接下来 n 行:每行两个整数 a[i], b[i] (1 ≤ a[i] ≤ m, 1 ≤ b[i] ≤ 1000)
输出格式
一个整数,表示最大收益
样例输入
4 10 2 3 3 4 4 5 5 6样例输出
10解题思路
这是经典的 0/1 背包问题。设 dp[j] 表示使用 j 单位资源能获得的最大收益。
状态转移方程:dp[j] = max(dp[j], dp[j - a[i]] + b[i]),其中 j 从 m 递减到 a[i]。
参考代码
#include<iostream>#include<vector>#include<algorithm>usingnamespacestd;intmain(){intn,m;cin>>n>>m;vector<int>a(n),b(n);for(inti=0;i<n;i++){cin>>a[i]>>b[i];}vector<int>dp(m+1,0);for(inti=0;i<n;i++){for(intj=m;j>=a[i];j--){dp[j]=max(dp[j],dp[j-a[i]]+b[i]);}}cout<<dp[m]<<endl;return0;}时间复杂度
O(n×m),对于 n ≤ 100, m ≤ 1000 完全可行。
总结与备考建议
1. 时间分配策略
- T1、T2:30-40分钟(确保全对)
- T3:60-70分钟(争取高分)
- T4:60-70分钟(尽力而为)
- 剩余时间:检查调试
2. 常见考点
- 基础语法和输入输出
- 模拟和枚举
- 排序和查找
- 简单动态规划
- 基础数据结构(数组、队列、栈)
- 简单图论(BFS、DFS)
3. 调试技巧
- 使用样例测试
- 边界情况测试(n=1, m=1, 最大值等)
- 中间输出调试
- 对拍(编写暴力程序对比)
4. 注意事项
- 仔细阅读题目,注意数据范围
- 使用合适的数据类型(long long)
- 注意数组下标从0还是1开始
- 及时取模防止溢出
- 文件名和读写方式要正确
学习资源推荐
在线评测平台
- 洛谷(www.luogu.com.cn)
- Codeforces(codeforces.com)
- 力扣(leetcode.cn)
参考书籍
- 《算法竞赛入门经典》
- 《信息学奥赛一本通》
- 《挑战程序设计竞赛》
视频教程
- B站:各类算法竞赛入门课程
- 中国大学MOOC:程序设计基础
希望这份题解对您备考CSP-J2有所帮助!祝您取得好成绩!
