云计算百科
云计算领域专业知识百科平台

信奥赛csp初赛【完善程序】(解题方法与技巧详解)

信奥赛csp初赛【完善程序】(解题方法与技巧详解)

一、题型概述

完善程序题是CSP-J第一轮(初赛)的第三部分,通常由2道大题、10个填空组成,每小题3分,共30分。题目会给出一段不完整的C++程序(约70%-85%的代码),挖掉4-6处关键代码,要求考生从4个选项中选出正确答案补全。

二、核心方法与技巧

技巧1:深度审题——理解“做什么”和“怎么做”

拿到题目后,先不要看代码,认真读题目的问题描述:

  • 题目要解决什么问题?(如“判断一个数是否为完全平方数”)
  • 输入是什么?输出是什么?
  • 有没有特殊的约束条件?

小例子:如果题目说“给定一个正整数n,判断它是不是完全平方数”,你马上要知道——需要找一个整数x,使得x²=n,x从1开始试到√n就够了。

技巧2:变量命名分析法

通过变量名初步判断变量作用:

  • cnt / count → 计数器
  • ans / result → 最终答案
  • dp → 动态规划的状态数组
  • vis → 访问标记
  • left / right / mid → 二分查找的左右边界和中间值

小例子:看到int left = 0, right = nums.size() – 1;和mid = left + (right – left) / 2;,马上判断这是二分查找的框架。

技巧3:算法逆向构想

不看代码,先自己想:如果让我写这个程序,我会用什么算法?每一步怎么写?

有了自己的思路后,再去对比题目给出的代码框架,填空处就很容易判断了。

小例子:判断平方数——自己先想:我会设i=1,循环到√n,判断i*i==n。再看代码,空①应该填1,空②应该填√n。

技巧4:结构化通读——抓住代码骨架

先忽略空格,通读整个程序,理解:

  • 主函数做了什么?(输入、调用、输出)
  • 子函数做了什么?(核心算法)
  • 循环结构是怎样的?(单层还是嵌套?边界是什么?)
技巧5:顺序优先策略——先易后难

从最直观的空入手:

  • 变量初始化(如sum = 0、i = 0、flag = false)
  • 循环的起止条件
  • 函数返回值

先把简单的空填了,建立信心,同时也能通过已填的空理解更多代码逻辑,帮助解决难题。

技巧6:代入法(“骗分”技巧)

对于拿不准的题目,把4个选项分别代入,看哪个选项让程序逻辑最通顺、运行结果最合理。

小例子:如果空处是一个if条件,把A、B、C、D分别代入,看哪个条件下程序的执行路径最符合题目要求。

技巧7:样例验证法

填完所有空后,用题目给的样例(或自己构造简单数据)手工模拟执行一遍程序:

  • 用n=1、n=2等边界值测试
  • 看每一步变量的变化是否符合预期
  • 确认最终输出是否正确

三、真题分析(一):2024年 CSP-J 完善程序题——判断平方数

问题描述:给定一个正整数 n,判断这个数是不是完全平方数,即存在一个正整数 x 使得 x 的平方等于 n。试补全程序。

#include<iostream>
#include<cmath>
using namespace std;

bool isSquare(int num){
int i = ____①____;
int bound = ____②____;
for(; i <= bound; ++i){
if( ____③____ ){
return ____④____;
}
}
return ____⑤____;
}

int main(){
int n;
cin >> n;
if(isSquare(n)){
cout << n << " is a Square number" << endl;
}else{
cout << n << " is not a Square number" << endl;
}
return 0;
}

选项:

① A. 1 B. 2 C. 3 D. 4

② A. (int)floor(sqrt(num))-1 B. (int)floor(sqrt(num)) C. floor(sqrt(num/2))-1 D. floor(sqrt(num/2))

③ A. num =

2

i

2*i

2i B. num ==

2

i

2*i

2i C. num =

i

i

i*i

ii D. num ==

i

i

i*i

ii

④ A. num =

2

i

2*i

2i B. num ==

2

i

2*i

2i C. true D. false

⑤ A. num =

2

i

2*i

2i B. num ==

2

i

2*i

2i C. true D. false

方法技巧应用分析

技巧1(深度审题) : 题目要求判断n是否为完全平方数——即是否存在正整数x使x²=n。最小的正整数是1,所以i应该从1开始试。

技巧2(变量命名分析) :

  • num → 要判断的数
  • i → 循环变量,代表尝试的x值
  • bound → 循环的上限

技巧3(算法逆向构想) : 自己写这个程序:

i从1开始
bound = sqrt(num)(向下取整)
循环i从1到bound:
如果 i*i == num → 返回true
循环结束 → 返回false

技巧6(代入法应用) :

空①:代入A(1)——从1开始试,正确。代入B(2)——漏掉了1²=1的情况,错误。

空②:代入B——(int)floor(sqrt(num)),正好是√num向下取整,正确。代入A——减1会漏掉边界情况(如num=4,√4=2,减1变成1,漏掉2²=4)。

空③:需要判断i*i是否等于num。A和C用的是赋值号=(不是比较),B是2*i(不是平方),只有D正确。

空④:找到后应返回true(选项C)。

空⑤:循环结束没找到,返回false(选项D)。

正确答案

① A(1) ② B (int)floor(sqrt(num)) ③ D(num == i*i) ④ C(true) ⑤ D(false)

四、真题分析(二):2022年 CSP-J 完善程序题——枚举因数

问题描述:从小到大打印正整数 n 的所有正因数。试补全枚举程序。

#include <bits/stdc++.h>
using namespace std;

int main(){
int n;
cin >> n;

vector<int> fac;
fac.reserve((int)ceil(sqrt(n)));

int i;
for (i = 1; i * i < n; ++i){
if (){
fac.push_back(i);
}
}

for (int k = 0; k < fac.size(); ++k){
cout <<<< "";
}
if () {
cout <<<< "";
}
for (int k = fac.size() 1; k >= 0; k){
cout <<<< "";
}
}

①~⑤处应填( )

  • ①处选项:
    • A. n % i == 0
    • B. n % i == 1
    • C. n % (i-1) == 0
    • D. n % (i-1) == 1
  • ②处选项:
    • A. n / fac[k]
    • B. fac[k]
    • C. fac[k]-1
    • D. n / (fac[k]-1)
  • ③处选项:
    • A. (i-1)*(i-1)== n
    • B. (i-1)*i == n
    • C. i*i == n
    • D. i*(i-1) == n
  • ④处选项:
    • A. n-i
    • B. n-i+1
    • C. i-1
    • D. i
  • ⑤处选项:
    • A. n / fac[k]
    • B. fac[k]
    • C. fac[k]-1
    • D. n / (fac[k]-1)

  • 方法技巧详细应用分析
    • 技巧1(深度审题)+ 技巧3(逆向构想)应用: 题目要求“从小到大”打印。我的构想是:先找所有“小因数”(≤√n)存起来,它们天然升序;如果n是完全平方数,中间那个数单独输出;最后反向遍历小因数数组,输出n / 小因数,得到的就是升序的大因数。带着这个构想来看代码,三段输出(②、④、⑤)分别对应我的三步,逻辑完全咬合。
    • 技巧2(变量名分析)应用: fac就是存小因数的数组。i作为循环变量,i * i < n说明i最大只取到√n之前,这印证了“只存一半因数”的猜想。
    • 技巧4(结构化通读)+ 技巧5(先易后难)应用: 先找最简单的空:空④——它是特判完全平方数后输出的数,显然输出当前的i(即√n),直接选 D。空③——判断完全平方数,循环条件是i*i < n,跳出循环时i满足i*i >= n,所以只需判断i*i == n,选 C。两个简单空先搞定。
    • 技巧6(代入法)攻克难点:
      • 空①:判断i是否为因数。代入A n % i == 0,如果余数为0说明整除,压入数组,符合逻辑。代入B是余数为1,无意义,排除。选 A。
      • 空②:正序输出小因数。代入B fac[k],正好逐个输出存好的小因数(如1,2,3)。代入A是输出大因数,顺序不对,排除。选 B。
      • 空⑤:倒序输出大因数。代入A n / fac[k],例如n=12,fac存了[1,2,3],倒序取k=2得3,输出12/3=4;k=1得2,输出6;k=0得1,输出12。得到4 6 12,拼接前面输出的1 2 3和平方根(无),结果为1 2 3 4 6 12,完全正确!选 A。
    最终答案

    ① A ② B ③ C ④ D ⑤ A

    五、总结

    完善程序题的核心是理解算法逻辑而非死记语法。做题时按以下顺序操作:

  • 读题:明确要解决什么问题
  • 自己想:如果自己写会用什么算法
  • 读代码:抓住变量含义和代码结构
  • 先易后难:先填初始化、返回值等简单空
  • 代入验证:拿不准时把选项代入试试
  • 样例检验:填完后用简单数据模拟运行
  • 掌握这“六步法”,定拿高分!


    更多内容请关注专栏:信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转


    【秘籍汇总】(完整csp信奥赛C++学习资料):

    1、csp/信奥赛C++,完整信奥赛系列课程(永久学习):

    https://edu.csdn.net/lecturer/7901 点击跳转

    在这里插入图片描述

    2、CSP信奥赛C++竞赛拿奖视频课:

    https://edu.csdn.net/course/detail/40437 点击跳转 在这里插入图片描述 https://edu.csdn.net/course/detail/41081 点击跳转 在这里插入图片描述

    3、csp信奥赛高频考点知识详解及案例实践:

    CSP信奥赛C++动态规划: https://blog.csdn.net/weixin_66461496/category_13096895.html点击跳转

    CSP信奥赛C++标准模板库STL: https://blog.csdn.net/weixin_66461496/category_13108077.html 点击跳转

    信奥赛C++提高组csp-s知识详解及案例实践: https://blog.csdn.net/weixin_66461496/category_13113932.html 点击跳转

    4、csp信奥赛冲刺一等奖有效刷题题解:

    信奥赛C++普及组CSP-J一等奖通关刷题题单及题解: https://blog.csdn.net/weixin_66461496/category_12673810.html 点击跳转

    信奥赛C++普及组csp-j初赛&复赛真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12808781.html 点击跳转

    信奥赛C++提高组csp-s初赛&复赛真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_13125089.html 点击跳转

    5、GESP C++考级真题题解:

    在这里插入图片描述

    GESP(C++ 一级+二级+三级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12858102.html 点击跳转

    在这里插入图片描述

    GESP(C++ 四级+五级+六级)真题题解(持续更新):https://blog.csdn.net/weixin_66461496/category_12869848.html 点击跳转

    在这里插入图片描述 GESP(C++ 七级+八级)真题题解(持续更新): https://blog.csdn.net/weixin_66461496/category_13117178.html 点击跳转

    · 文末祝福 ·

    #include<bits/stdc++.h>
    using namespace std;
    int main(){
    cout<<"跟着王老师一起学习信奥赛C++";
    cout<<" 成就更好的自己! ";
    cout<<" csp信奥赛一等奖属于你! ";
    return 0;
    }

    在这里插入图片描述

    赞(0)
    未经允许不得转载:网硕互联帮助中心 » 信奥赛csp初赛【完善程序】(解题方法与技巧详解)
    分享到: 更多 (0)

    评论 抢沙发

    评论前必须登录!