C++信奥洛谷循环章节练习题
📚 C++ 算法基础笔记 (Day 424)
P2669 [NOIP 2015 普及组] 金币
🏷️ 核心考点: 嵌套循环、累加器、找规律
题目大意: 骑士第1天拿1枚金币,第2-3天每天拿2枚,第4-6天每天拿3枚……以此类推。求前 k 天总共拿了多少金币。
解题思路:
外层循环控制天数,从第1天循环到第 k 天。
内层逻辑控制每天发多少金币。我们可以发现,发 i 枚金币会持续 i 天。
使用一个变量记录当前应该发的金币数,另一个变量记录该数量还需要发几天。
C++ 关键点:
变量初始化: 累加金币的变量 sum 必须初始化为 0。
循环控制: 注意循环的终止条件,不要超出总天数 k。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intk,total=0,coins=1,days=0;cin>>k;for(inti=1;i<=k;i++){total+=coins;days++;//这个阶段又多了一天if(days==coins){//如果这个阶段发完了coins++;days=0;}}cout<<total;return0;}P1423 小玉在游泳
🏷️ 核心考点: while 循环、浮点数运算、精度问题
题目大意: 小玉第一步游 2 米,之后每一步都是上一步的 98%。问游够 s 米至少需要几步?
解题思路:
这是一个典型的“直到型”循环问题。
使用 while 循环,只要总距离小于目标距离 s,就继续游。
每次循环中:步数+1,当前步长 times 0.98,总距离累加。
C++ 关键点:
数据类型: 距离和小数步长必须使用 double 或 float,不能用 int。
循环条件: 注意是 < 还是 <=,题目通常要求“达到或超过”,所以循环条件通常是 total < s。
#include<bits/stdc++.h>usingnamespacestd;intmain(){doubles,m=2,total=0;intc=0;cin>>s;while(s>total){total+=m;m*=0.98;c++;}cout<<c;return0;}P1307 [NOIP 2011 普及组] 数字反转
🏷️ 核心考点: 取模运算 %、整除 /、前导零处理
题目大意: 给定一个整数,将其反转(例如 123 变 321,-380 变 -83)。
解题思路:
方法一(数学法):
判断正负号。
通过 n % 10 取出最后一位,n / 10 去掉最后一位。
利用 ans = ans * 10 + digit 构建反转后的数字。
方法二(字符串法): 将数字作为字符串读入,倒序遍历输出。
C++ 关键点:
前导零: 如果输入是 1200,反转后是 0021,输出应为 21。数学法自动解决了这个问题,字符串法需要手动跳过开头的 ‘0’。
负数处理: 记得先输出负号,再处理数字部分。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,r=0,m=0;cin>>n;boolt=false;if(n<0){n=-n;t=true;}while(n!=0){r=n%10;//123m=m*10+r;//30+2--320+1n/=10;}if(t){m=-m;}cout<<m;return0;}P1420 最长连号
🏷️ 核心考点: 数组遍历、计数器重置、打擂台算法
题目大意: 在 n 个整数中,找出数值连续递增(相差为1)的最长片段长度。
解题思路:
定义两个变量:current_len(当前连号长度)和 max_len(最大连号长度)。
从第2个数开始遍历,如果 a[i] == a[i-1] + 1,说明连上了,current_len++。
否则,说明断了,比较并更新 max_len,然后将 current_len 重置为 1。
注意: 循环结束后,还要再比较一次 max_len 和 current_len(防止最长连号出现在数组末尾)。
C++ 关键点:
初始化: max_len 至少为 1(因为单个数字也是长度为1的连号)。
边界检查: 循环结束后别忘了最后一次更新最大值。
#include<bits/stdc++.h>usingnamespacestd;intn,a[10005];intmain(){cin>>n;for(inti=0;i<n;i++){cin>>a[i];}intans=1,c=1;for(inti=1;i<n;i++){if(a[i]==a[i-1]+1)c++;elsec=1;if(c>ans)ans=c;}cout<<ans;return0;}P1075 [NOIP 2012 普及组] 质因数分解
🏷️ 核心考点: 质数判断、因数分解、开方优化
题目大意: 已知正整数 n 是两个不同质数的乘积,求较大的那个质数。
解题思路:
从最小的质数 2 开始尝试除 n。
一旦找到一个能整除 n 的数 i,那么 i 一定是较小的那个质数(因为是从2开始找的)。
另一个质数就是 n / i。
输出 n / i 即可。
C++ 关键点:
效率: 其实只需要循环到 sqrt{n} 即可。
逻辑: 题目保证了 n 一定是两个质数乘积,所以找到的第一个因数必然是质数,不需要额外写 is_prime 函数判断。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn;cin>>n;for(inti=2;i*i<=n;i++){if(n%i==0){cout<<n/i;return0;}}return0;}P5726 【深基4.习9】打分
🏷️ 核心考点: 数组排序、求和、求最值
题目大意: n 个评委打分,去掉一个最高分,去掉一个最低分,求平均分。
解题思路:
读入所有分数存入数组。
计算总分 sum。
遍历数组找出 max_score 和 min_score。
计算公式:(sum - max_score - min_score) / (n - 2)。
C++ 关键点:
数据类型: 平均分通常有小数,计算结果要转为 double。
保留小数: 输出通常需要保留2位小数,使用 printf(“%.2f”, ans) 或 cout << fixed << setprecision(2) << ans;。
#include<bits/stdc++.h>usingnamespacestd;intmain(){intn,num,ma=-1000,mi=1000;doubles=0;cin>>n;for(inti=0;i<n;i++){cin>>num;s+=num;if(num>ma){ma=num;}if(num<mi){mi=num;}}s=s-ma-mi;doubleavg=s/(n-2);printf("%.2lf",avg);return0;}💡 给同学们的复习建议
多动手写代码: 不要只看思路,一定要在编译器里把代码敲一遍,特别是循环的边界条件。
注意变量类型: 看到小数一定要用 double,看到大整数(超过20亿)要考虑 long long。
调试技巧: 如果结果不对,试着在循环里 cout 中间变量的值,看看是在哪一步出错的。
