一、上一讲复习习题
(每题 1 1 1 分,共 4 4 4 分)
1.下面代码的错误有哪些?
if(n%2==0){
cout<<"Is a even.";
else{
cout<<"Is a odd."
}
}
n
未定义,且没有初始值。else
语句写的位置错误,应在if
语句的后面写。- 第四行
cout<<"Is a odd."
处没有分号。 else
在C++中没有定义,压根不能用,而不是位置错。
2.这个判断闰年的核心代码,是对的还是错的?
//year表示当前年份
cin>>year;
if(n/4==0&&n%400!=0){
cout<<"Is a leap.";
}
if(n%400==0){
cout<<"Is a leap.";
}
else{
cout<<"Is not a leap.";
}
- 正确。
- 错误。有_______处错误。
3.下面是洛谷 P5716的核心代码,请说出下面代码的问题。
//year表示年份,month表示月份,isleap表示是否为闰年。
cin>>year>>month;
if(year%4==0||year%400==0){
isleap=true;
}
else{
isleap=false;
}
if(month=1||month=3||month=5||month=7||month=8||month=10||month=12){
cout<<"31"<<endl;
}
else if(month==4&&month==6&&month==9&&month==11){
cout<<"30"<<endl;
}
else if(month==2){
if(isleap){
cout<<"29"<<endl;
}
else{
cout<<"28"<<endl;
}
}
- 答:______________________________________________________________________________________________________。
4.读程序选输出。阅读程序,选择它的正确输出。(禁止运行程序)
#include<iostream>
using namespace std;
int main(){
int b=4,a=1,c=4;
int root=b*b-4*a*c;
if(root>0){
cout<<"2"<<endl;
}
else if(root==0){
cout<<1<<endl;
}
else{
cout<<0<<endl;
}
return 0;
}
"1"
- 没有输出
0
1
"2"
二、循环结构课堂讲义
引导、概念普及
概念1:程序设计结构基础三要素:顺序结构、分支结构、循环结构。
概念2:程序设计基础掌握内容:顺序结构、分支结构、循环结构、一/多维数组、字符串、函数/函数递归的理解。
一、for
循环
我们要列举大于等于数字 1 1 1 ,小于数字 6 6 6 的数字,怎么办呢?相信同学们都已经想好怎么写了,核心代码如下:
cout<<1<<endl;
cout<<2<<endl;
cout<<3<<endl;
cout<<4<<endl;
cout<<5<<endl;
如果我们要列举 99 99 99 个数, 999 999 999 个数, 9999 9999 9999 个数, 99999 99999 99999 个甚至更多的数,用这种方法岂不太低效了?
别急,我们可以用for
循环解决。列举
1
1
1 到
99
99
99 的数的核心代码如下:
for(int i=1;i<100;i=i+1){
cout<<i<<endl;
}
这里每个部分是什么呢?
for
关键字到}
结束的地方称为for
循环。它是一种循环结构。
for
后面()
内三个部分由;
分隔,分别表示:进入循环前执行的语句(循环初始化)、循环继续执行一次的条件判断(循环条件),每一次循环执行后会执行的语句(循环后执行语句)。
任务1:分别输出
1
1
1 至
100
,
1000
,
10000
,
100000
,
1000000
100,1000,10000,100000,1000000
100,1000,10000,100000,1000000 的连续数字,想想怎么做?提示:我们可以用for
循环解决问题。(
3
3
3 分)
答案:标程链接
任务2:
100
100
100 以内的正偶数。提示:每次i
不一定+1
,或用if
解决问题?(
3
3
3 分)
答案:标程链接
二、自增和自减
我们要学习特殊的运算符,快速修改变量的值。
在之前的课程中,我们经常见到digit=digit+1
,digit=digit-1
这样的语句。不难发现,表达式中=
右边的值会被先计算出来,赋给=
左边的digit
(右结合),其起到了让digit+1
的效果。
我们可以将x=x+1
简写成x+=1
,类似的还有-=
,*=
,/=
,%=
等。
当我们对变量的值进行操作,每次增加或减少的量为确定的
1
1
1 时,C++语言还专门提供了专门的 自增运算符(increment operator) ++
和 自减运算符(decrement operator) --
。
如果我们写a++
或++a
,它实际达到的效果与a=a+1
或a+=1
都是完全一致的。而如果我们写a--
或--
a则与a=a-1
或a-=1
在效果上等价。
cout<<(a++);
cout<<(++a);
假设现在a
的取值为5
,上面这两行代码中第一句会输出的值是5
;而同样在a
取值为5
的情况下,使用第二句则会输出6
。这是因为表达式a++
先被使用,之后再将a
的值增加1
,而++a
则是先将a
的值增加1
然后才被使用!
在运算的速度上,速度的快慢如下:
++a > a++ > a+=1 > a=a+1
--a > a-- > a-=1 > a=a-1
任务三:输出 1 1 1 至 n n n 之间的连续正整数,要求使用新学的特殊符号。( 3 3 3 分)
答案:标程链接
知识:循环 n n n 次有 2 2 2 种写法,代码如下:
示例 1 1 1 :
int n;
cin>>n;
for(int i=1;i<=n;i++/*++i*/){
}
示例 2 2 2 :
int n;
cin>>n;
for(int i=0;i<n;i++/*++i*/){
}
三、求和/积模型
1.求 1 1 1 到 n n n 的和。
解法一:运用公式求解
( 1 + n ) × n 2 \LARGE{\frac{(1+n)\times n}{2}} 2(1+n)×n
代码实现:
int n;
cin>>n;
cout<<(1+n)*n/2<<endl; //公式
解法二:利用循环累加求解
我们定义一个变量 s u m sum sum ,初始化为 0 0 0 ,从 1 1 1 循环到 n n n ,每次累加到 s u m sum sum 中,即可得出正确结果。注意:输出的是 s u m sum sum ,不是 n n n !
代码实现:
int sum=0,n;
cin>>n;
for(int i=1;i<=n;i++){
sum+=i; //循环求解的关键
}
cout<<sum<<endl;
思考:如果求 1 1 1 到 n n n 的乘积 ( n ! n! n!),怎么办呢?
解法:利用循环求乘积
我们定义一个变量 f r a c frac frac ,初始化为 1 1 1 ,从 1 1 1 循环到 n n n ,每次乘到 f r a c frac frac 中,即可得出正确结果。注意: f r a c frac frac 的值必须初始化为 1 1 1 !
代码实现:
unsigned long long frac=1; //unsigned是一个整数类型,比 long long 还大。
int n;
cin>>n;
for(int i=1;i<=n;i++){
frac*=i; //同上
}
cout<<frac<<endl;
四、计数器模型
输入 n n n ,请找出 1 1 1 到 n n n 之间是 7 7 7 的倍数的个数。
解法:利用条件判断解决
我们定义一个计数器 c n t cnt cnt 为 0 0 0 ,表示目前尚未由满足要求的数。从 1 1 1 循环到 n n n ,如果这个数满足条件,那么 c n t cnt cnt 加 1 1 1 ,否则跳过,最后输出 c n t cnt cnt 。
代码实现:
int n,cnt=0;
cin>>n;
for(int i=1;i<=n;i++){
if(i%7==0){ //重要的条件判断部分,计数器模型的核心
cnt++;
}
}
cout<<cnt<<endl;
总结的计数器模型:
int n,cnt=0; //初始化很重要!
cin>>n;
for(int i=1;i<=n;i++){
if(/*条件部分*/){
cnt++;
}
}
cout<<cnt<<endl;
任务4:计算 1 − n 1-n 1−n 的和。( 1 1 1 分)
任务5:计算
n
!
n!
n! (
n
n
n 的阶乘),数据大,要用unsigned long long
解题。(
1
1
1 分)
任务6:计算 m m m 到 n n n 之间个位是 7 7 7 的倍数的个数,保证 7 ≤ m ≤ n 7\leq m\leq n 7≤m≤n 。( 10 10 10 分)
五、进阶的求和/积模型
输入 n n n 和 n n n 个正整数,求所有正整数(不包含 n n n)的总和/乘积。
解法:运用循环累加求解
和之前的求和/积模型一样,我们同样定义一个变量 s u m sum sum ,并初始化为 0 0 0 ,循环 n n n 次,在循环内部定义一个临时变量 x x x ,在这里, x x x 只在此次循环中有效。输入 x x x ,并将其累加到 s u m sum sum 中,输出 s u m sum sum ,亦可得出正确结果。
代码实现:
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
int x; //临时变量
cin>>x;
sum+=x; //关键
}
cout<<sum<<endl;
求 n n n 个数的乘积怎么办呢?
解法:运用循环乘求解
同样,我们定义一个变量 s u m sum sum ,并初始化为 1 1 1 ,循环 n n n 次,在循环内部定义一个临时变量 x x x ,在这里, x x x 只在此次循环中有效。输入 x x x ,并将其乘到 s u m sum sum 中,输出 s u m sum sum ,亦可得出正确结果。注意: s u m sum sum 必须初始化为 1 1 1 !
代码实现:
int n,sum=1; //必须初始化为1!
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
sum*=x; //关键
}
cout<<sum<<endl;
六、求最大/最小的数(打擂台算法)
大家看过电视节目吗?在节目中,怎么确定最强的人呢?①把第一个人作为擂主。②挑战者上台与擂主比赛。③如果挑战者胜,则其成为新的擂主,如果挑战者败,则原擂主还是擂主。重复②、③步骤,直到所有人比完。最终的擂主为最强的人。
在求最大/最小的数时,我们也可以把数比大小的过程比作打擂台。比如在1 8 9 4 3 10
六个数中,我们定义变量max
初始化为-0x7fffffff
(一个很大的负数,0x
是十六进制的开头,等于十进制的2147483647
),以便让第一个数尽快替换max
。
求最大值的模拟过程:把1
定为挑战者,1
比ffffffff80000001(HEX)/-2147483647(DEC)
大,1
为擂主。把8
定为挑战者,8
比1
大,8
为擂主。把9
定为挑战者,9
比8
大,9
为擂主。把4
定为挑战者,4
没有9
大,9
依然为擂主。把3
定为挑战者,3
没有9
大,9
依然为擂主。把10
定为挑战者,10
比9
大,10
为擂主。因此,在这些数中,10
是最大的。
求最小值的模拟过程:把1
定为挑战者,1
比7fffffff(HEX)/2147483647(DEC)
小,1
为擂主。把8
定为挑战者,8
没有1
小,1
依然为擂主。把9
定为挑战者,9
没有1
小,1
依然为擂主。把4
定为挑战者,4
没有1
小,1
依然为擂主。把3
定为挑战者,3
没有1
小,1
依然为擂主。把10
定为挑战者,10
没有1
小,1
依然为擂主。因此,在这些数中,1
是最小的。
代码实现(求最大值):
int n,max=-0x7fffffff; //一开始的擂主
cin>>n;
for(int i=1;i<=n;i++){
int temp;
cin>>temp; //挑战者
if(temp>max){ //如果挑战者的值大于擂主的值
max=temp; //挑战者成为新的擂主
}
}
cout<<max<<endl; //最终的擂主就是最大值
代码实现(求最小值):
int n,min=0x7fffffff; //一开始的擂主
cin>>n;
for(int i=1;i<=n;i++){
int temp;
cin>>temp; //挑战者
if(temp<min){ //如果挑战者的值小于擂主的值
min=temp; //挑战者成为新的擂主
}
}
cout<<min<<endl; //最终的擂主就是最小值
任务 7 7 7 :
七、保留几位小数
n n n 名同学在分 x m L xmL xmL 的肥宅快乐水,每名同学分到了多少毫升的肥宅快乐水?如果是 5 5 5 名同学分 500 m L 500mL 500mL 的肥宅快乐水,那么每名同学能分到 500 ÷ 5 = 100 ( m L ) 500\div5=100(mL) 500÷5=100(mL) 的快乐水,那么 3 3 3 名同学分 100 m L 100mL 100mL 的快乐水,每名同学就会分到 100 ÷ 3 = 100 3 ( m L ) 100\div3=\frac{100}{3}(mL) 100÷3=3100(mL) 的快乐水。程序不会那么智能,输出 100 3 \frac{100}{3} 3100 或者 33. 3 ˙ 33.\dot{3} 33.3˙ ,一般来说,题目会让我们保留几位小数(四舍五入)。
怎么实现保留几位小数呢?C++中,<iomanip>
头文件为我们提供了保留几位小数的语句,能实现四舍五入保留小数位数的目的。其语句用法为cout<<fixed<<setprecision([保留的小数位数])<<[需要保留位数的变量];
比如我们要让 100 ÷ 3 100\div3 100÷3 的结果保留两位小数,怎么办哪,代码如下:
cout<<fixed<<setprecision(2)<<100/3<<endl;
这样的写法是错误的!程序会输出33.00
而不是我们想要的33.33
,因为100
和33
都是int
类型的常量,结果也是int
类型,100/3
的结果为33
,再保留两位小数,结果就是33.00
了。遇到这样的问题我们有两种解决办法:1.在100/3
的前面加上一个(double)
,强制转换为double
类型,这样就可以正确输出了。2.在100/3
前面加上1.0*
,这样会让double
类型的常量1.0
乘100
和33
,double
的int
做运算,都会隐式转移为double
类型。
注意!<<fixed<<setprecision(2)
在整个程序中一直有效!**输出两个数
9.47854485
9.47854485
9.47854485 和
0.56666464
0.56666464
0.56666464 ,要求第一个数保留两位小数,对错代码分别如下(Assume that <iostream> and <iomanip> has been included
):
错误:
cout<<fixed<<setprecision(2)<<9.47854485<<" "<<0.56666464<<endl;
正确(无法用现在的知识解决)(Assume that <cstdio> has been included
):
printf("%.2lf ",9.47854445);
printf("%lf\n",0.56666464);
八、平均值算法
首先,输入一个正整数 n n n ,再输入 n n n 个整数 a 1 − a n a_1-a_n a1−an ,求出 a 1 − a n a_1-a_n a1−an 的平均值。
我们知道了求平均值的公式,假如数的个数为 x x x , x x x 个数为 a 1 − a x a_1-a_x a1−ax ,那么公式如下:
a 1 + a 2 + ⋅ ⋅ ⋅ + a x − 1 + a x x \LARGE{\frac{a_1+a_2+···+a_{x-1}+a_x}{x}} xa1+a2+⋅⋅⋅+ax−1+ax
我们先输入正整数
n
n
n ,在定义double
类型的
s
u
m
sum
sum ,利用求和模型求出
n
n
n 个数的和,最后输出
s
u
m
÷
n
sum\div n
sum÷n 的结果,按题目要求保留几位小数,这里默认保留
2
2
2 位。(整数和浮点数通用)
代码实现:
int n;
double sum=0;
cin>>n;
for(int i=1;i<=n;i++){
double x;
cin>>x;
sum+=x;
}
cout<<fixed<<setprecision(2)<<sum/n<<endl;
三、动态规划(dp)讲义
敬请期待~~~
四、课后习题
1.完成计蒜客 循环的使用 思维拓展习题
2.完成洛谷循环结构入门题,题目如下:
声明:本讲义由 The YU Team Admin Wu yuyin 编撰,如需转载请得到 The YU Team 的管理员许可,并且附上此声明,否则将严肃处理。
主要参考:计蒜客课程内容-循环结构
Powered by The YU Team