while 循环
回顾上节的最后我们学了用 if
进行判断,
if(条件)
{
操作;
}
while
循环也是一个类似的结构:
while(条件)
{
操作;
}
区别在于 while
没有类似 else
的操作,而且如果满足条件,则会重复执行大括号内的操作;而if
只会执行其中的一次操作。
题目描述
给定一个小于等于 1000 1000 1000 的正整数 n n n ,求 1 1 1 到 n n n 中所有数的累加和。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n ;
scanf("%d" ,&n);
int i = 1 , sum = 0 ;
while(i <= n)
{
sum += i ;
i ++ ;
}
printf("%d" ,sum) ;
return 0 ;
}
数学方法可以直接考虑利用等差数列求和公式 ( 首项 + 末项 ) × 项数 2 {(首项 + 末项) \times 项数}\over 2 2(首项+末项)×项数 ,但是这个题数据范围比较小,所以也可以通过模拟的方式来完成这个过程。
注意一定要给 sum 赋初始值0
当我们在主函数内声明变量时,通常没有固定的初始值,我们将 i i i 从 1 1 1 加到 n n n ,每次加一,实现了从 1 1 1 到 n n n 所有整数的枚举,然后将这些数全部加到 s u m sum sum 上,则 s u m sum sum 即为所求的答案。
题目描述
给出 n n n 和 n n n 个整数 a i a_i ai,求这 n n n 个整数中最小值是什么。
输入格式
第一行输入一个正整数 n n n,表示数字个数。
第二行输入 n n n 个非负整数,表示 a 1 , a 2 … a n a_1,a_2 \dots a_n a1,a2…an,以空格隔开。
输出格式
输出一个非负整数,表示这 n n n 个非负整数中的最小值。
样例输入
8
1 9 2 6 0 8 1 7
样例输出
0
提示
数据保证, n ≤ 100 n\le100 n≤100 且 0 ≤ a i ≤ 1000 0\le a_i \le 1000 0≤ai≤1000。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n , a , ans = 1000000000;
scanf("%d" ,&n);
while(n)
{
scanf("%d" ,&a) ;
if(ans > a) ans = a ;
n -- ;
}
printf("%d" ,ans) ;
return 0 ;
}
此时的 n n n 起到计数的作用,当然也可以另外设置一个 i i i 写成
int i = 1 ;
while(i <= n)
{
scanf("%d" ,&a) ;
if(ans > a) ans = a ;
i ++ ;
}
或者利用 n ++
这一写法先调用后修改的性质,写成
while(n --)
{
scanf("%d" ,&a) ;
if(ans > a) ans = a ;
}
for循环
f o r for for 循环结构看起来可能更麻烦,但是也挺好理解的:
for(初始; 判断 ; 更新)
{
操作;
//循环体
}
当进入
f
o
r
for
for 循环时先初始化,然后判断条件是否成立,若不成立则退出循环,若成立则执行相应操作,执行完操作后更新,再次判断条件是否成立,若不成立则退出,若成立则再次进行相应操作。
我们用
f
o
r
for
for 循环再写一遍上面两道题
题目描述
给定一个小于等于 1000 1000 1000 的正整数 n n n ,求 1 1 1 到 n n n 中所有数的累加和。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n , sum = 0 ;
scanf("%d" ,&n);
for(int i = 1; i <= n ; i ++)
{
sum += i ;
}
printf("%d" ,sum) ;
return 0 ;
}
其中 f o r for for 循环后的大括号也是可加可不加,如果只进行单个操作不用加,多个操作括起来。
题目描述
给出 n n n 和 n n n 个整数 a i a_i ai,求这 n n n 个整数中最小值是什么。
输入格式
第一行输入一个正整数 n n n,表示数字个数。
第二行输入 n n n 个非负整数,表示 a 1 , a 2 … a n a_1,a_2 \dots a_n a1,a2…an,以空格隔开。
输出格式
输出一个非负整数,表示这 n n n 个非负整数中的最小值。
样例输入
8
1 9 2 6 0 8 1 7
样例输出
0
提示
数据保证, n ≤ 100 n\le100 n≤100 且 0 ≤ a i ≤ 1000 0\le a_i \le 1000 0≤ai≤1000。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n , a , ans = 1000000000;
scanf("%d" ,&n);
for(int i = 1 ; i <= n ; i ++)
{
scanf("%d" ,&a) ;
if(a < ans) ans = a ;
}
printf("%d" ,ans) ;
return 0 ;
}
此时的 i i i 没有参与任何运算,只是用来计数也是可以的。
局部变量
注意,在两个 f o r for for 循环的举例代码中,我们的 i i i 是在 f o r for for 循环的初始化部分声明的变量,因此只能作为局部变量在大括号内使用,而不能在循环结构之外随意调用!
break; 与 continue;
break;
操作用在循环体中,表示退出循环。
continue;
操作用在循环体中,表示跳过本次循环的剩余操作,进入下一次循环。
当多层循环嵌套使用时,以上两项操作若在内层循环中,只会对内层循环产生影响。
继续做题巩固一下
题目描述
已知: S n = 1 + 1 2 + 1 3 + … + 1 n S_n= 1+\dfrac{1}{2}+\dfrac{1}{3}+…+\dfrac{1}{n} Sn=1+21+31+…+n1。显然对于任意一个整数 k k k,当 n n n 足够大的时候, S n > k S_n>k Sn>k。
现给出一个整数 k k k,要求计算出一个最小的 n n n,使得 S n > k S_n>k Sn>k。
输入格式
一个正整数 k k k。
输出格式
一个正整数 n n n。
样例输入
1
样例输出
2
提示
【数据范围】
对于 100 % 100\% 100% 的数据, 1 ≤ k ≤ 15 1\le k \le 15 1≤k≤15。
#include <bits/stdc++.h>
using namespace std;
int main()
{
double ans = 0 , k ;
int n = 1 ;
scanf("%lf" ,&k) ;
for( ; ans <= k ; n ++)
ans += 1.0 / n ;
printf("%d" ,n - 1) ;
return 0;
}
这个写法中 n n n 在最后输出,因此设为全局变量,同时 f o r for for 循环中无论是 初始化 ,判断 还是 更新 其实都是可以省略掉的,但是该有的结构还是要有,比如两个分号。
双层循环
题目描述
给出 n n n,请输出一个直角边长度是 n n n 的数字直角三角形。所有数字都是 2 2 2 位组成的,如果没有 2 2 2 位则加上前导 0 0 0。
输入格式
输入一个正整数 n n n。
输出格式
输出如题目要求的数字直角三角形。
样例输入
5
样例输出
0102030405
06070809
101112
1314
15
提示
数据保证, 1 ≤ n ≤ 13 1\le n\le13 1≤n≤13。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n , tot = 1;
scanf("%d" ,&n) ;
for(int i = 1 ; i <= n ; i ++)//第i层
{
for(int j = i ; j <= n ; j ++)//第i层有n - i + 1 个数,因此 j 从 i 到 n
{
printf("%02d" ,tot) ;
tot ++ ;
}
printf("\n") ;
}
return 0;
}
这个就体现了双重循环,每次进入内层的 j循环
时都重新把
j
j
j 初始化成了当前的
i
i
i ,用
t
o
t
tot
tot 记录这个数字三角形到了数字几。
printf("%02d" ,tot) ;
的写法就是说不满两位的数字通过补前导
0
0
0 的方式补成两位。
然后每次输出完当前的那一层就换行。
数组
当我们需要 3 3 3 个变量时可以声明 a , b , c a , b , c a,b,c ,那么当我们需要 100 100 100 个时呢?
可以 int a[100];
意思是声明整型数组
a
a
a 中括号里数字类比数列的下标,调用时就
a
[
1
]
,
a
[
2
]
,
a
[
3
]
a[1],a[2],a[3]
a[1],a[2],a[3] 这样的用。
int a[100] ; //声明一个包含100个元素的数组
a[1] = 666 ; //赋值与正常变量一样
int k = 5 ;
a[k] = 123 ;//下标可以是一个数,也可以是变量
a['a'] = 456 ; //甚至可以是一个字符,相当于其对应ascii码值
a[k + 1] = a[k] + a[1] ;
printf("%d" ,a[k + 1]) ; //输出
特别的,我们用什么样的 关键字 声明这个数组,这个数组就是什么数据类型的,就是说也可以用 char
声明字符型数组 或者 用 double
声明浮点型数组;基于下标可以是变量这一特性,也很容易地可以和 循环 结合起来使用;注意: 数组的下标是从
0
0
0 开始,到
n
−
1
n - 1
n−1 结束,即声明一个 int a[100]
这样的数组,只有下标为从
0
0
0 到
99
99
99 之间的整数时才是合法的!
题目描述
陶陶家的院子里有一棵苹果树,每到秋天树上就会结出 10 10 10 个苹果。苹果成熟的时候,陶陶就会跑去摘苹果。陶陶有个 30 30 30 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试。
现在已知 10 10 10 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹果的数目。假设她碰到苹果,苹果就会掉下来。
输入格式
输入包括两行数据。第一行包含 10 10 10 个 100 100 100 到 200 200 200 之间(包括 100 100 100 和 200 200 200)的整数(以厘米为单位)分别表示 10 10 10 个苹果到地面的高度,两个相邻的整数之间用一个空格隔开。第二行只包括一个 100 100 100 到 120 120 120 之间(包含 100 100 100 和 120 120 120)的整数(以厘米为单位),表示陶陶把手伸直的时候能够达到的最大高度。
输出格式
输出包括一行,这一行只包含一个整数,表示陶陶能够摘到的苹果的数目。
样例输入
100 200 150 140 129 134 167 198 200 111
110
样例输出
5
#include <bits/stdc++.h>
using namespace std;
int apple[20];
int main()
{
for(int i = 1 ; i <= 10 ; i ++)
scanf("%d" ,&apple[i]) ;
int tall , high , ans = 0 ;
scanf("%d" ,&tall) ;
high = tall + 30;
for(int i = 1 ; i <= 10 ; i ++)
if(high >= apple[i]) ans ++;
printf("%d" ,ans) ;
return 0;
}
学了 循环 和 数组 之后就不需要声明 10 10 10 个变量挨个输入了,在 主函数 内声明的变量在不赋初始值的情况下可能是任意数,在 主函数 外声明变量时默认为 0 0 0 。
二维数组
思考我们 一维数组 只是多一个下标,其实还可以有 二维数组 ,即int a[110][110];
这样的,可以思考为 一维数组 是一个 数列 ,二维数组 是一个矩阵,有横坐标和纵坐标,可以类比线代里的矩阵。
想要访问每个位置可以类比一维数组时用循环里的变量当做下标,二维数组就可以用双重循环来访问每个下标。