目录
- 前言
-
- [6. while循环](#6. while循环)
-
- [6.1 while语法形式](#6.1 while语法形式)
- [6.2 执行流程](#6.2 执行流程)
- [6.3 实践](#6.3 实践)
- [6.4 练习](#6.4 练习)
-
- 练习1:反向输出每一位
- 练习2:数位之和
- 练习3:求和1
- [练习4:含 k 个 3 的数](#练习4:含 k 个 3 的数)
- 练习5:角谷猜想
- 练习6:计算多项式的值
- [7. for循环](#7. for循环)
-
- [7.1 for循环语法形式](#7.1 for循环语法形式)
- [7.2 执行流程](#7.2 执行流程)
- [7.3 实践](#7.3 实践)
- [7.4 while和for对比](#7.4 while和for对比)
- [7.5 练习](#7.5 练习)
-
- 练习1:求和2
- 练习2:求平均年龄
- 练习3:奥运奖牌计数
- 练习4:鸡尾酒疗法
- 练习5:救援
- [ceil 和 floor 函数](#ceil 和 floor 函数)
- 练习6:计算分数加减表达式的值
- 练习7:求分数序列和
- [8. do-while 循环](#8. do-while 循环)
-
- [8.1 do-while语法形式](#8.1 do-while语法形式)
- [8.2 执行流程](#8.2 执行流程)
- [8.3 实践](#8.3 实践)
- [8.4 练习](#8.4 练习)
- [9. break和continue语句](#9. break和continue语句)
-
- [9.1 break和continue介绍](#9.1 break和continue介绍)
- [9.2 break举例](#9.2 break举例)
- [9.3 continue举例](#9.3 continue举例)
- [9.4 练习](#9.4 练习)
-
- [练习: 质因数分解](#练习: 质因数分解)
- 解析:
- [10. 循环嵌套](#10. 循环嵌套)
-
- [10.1 循环嵌套的使用](#10.1 循环嵌套的使用)
- [10.2 练习](#10.2 练习)
-
- 练习1:包含数字9的数
- 练习2:斐波那契数列
- [练习3:求出 e 的值](#练习3:求出 e 的值)
- 练习4:三角形
- [练习5: 画矩形](#练习5: 画矩形)
- [练习6:第 n 小的质数](#练习6:第 n 小的质数)
- 练习7:水仙花数
- 总结
前言
本章会详细介绍每种语句和操作符的语法和使用方法,还会通过大量实例和练习题,帮助读者理解如何在实际编程中灵活运用这些工具。无论你是初学者,还是希望在算法竞赛中提升逻辑控制能力的进阶学习者,本章内容都将为你提供宝贵的指导。让我们一起开启这段探索条件判断与循环控制的编程之旅,为你的程序增添更多智能和效率;
6. while循环
C + + \mathsf{C}\substack{++} C++ 中有3种循环语句, while 就是其中一种,接下来就介绍一下 while 语句。
6.1 while语法形式
while 语句的语法结构和 if 语句非常相似,但不同的是 while 是用来实现循环的, if 是无法实现循环的。
下面是 while 循环的语法形式:
cpp
//形式1
while ( 表达式 )
语句;
if(表达式)
语句;
//形式2
//如果循环体想包含更多的语句,需要加上⼤括号
while ( 表达式 )
{
语句1;
语句2;
...
}
6.2 执行流程
首先上来就是执行判断表达式,表达式的值为 0 ,循环直接结束;表达式的值不为 0 ,则执行循环语句,语句执行完后再继续判断,是否进行下一次判断。
6.3 实践
题目:使用 while 循环在屏幕上打印 1 ∼ 10 \mathtt{1}{\sim}10 1∼10 的值
参考代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 1;
while (i <= 10)
{
cout << i << " ";
i = i+1;
}
return 0;
}
6.4 练习
练习1:反向输出每一位
输入一个正的整数,逆序打印这个整数的每一位
例如:
输入:1234,输出:4 3 2 1
输入:521,输出:1 2 5
小提示:
-
要想得到 n 的最低位,可以使用 n % 10 的运算,得到的余数就是最低位,如:1234 % 10 得到4
-
要想去掉n的最低位,找出倒数第二位,则使用 n = n / 10 \texttt{n}=\texttt{n}/\texttt{10} n=n/10 操作就可以去掉最低位的,如: n = 1234 / 1 ⊙ \scriptstyle\mathsf{n}=1234/1\odot n=1234/1⊙ 得到 123 ,123相较于1234就去掉了最低位, 123%10 就得到倒数第二位 3 。
-
循环1和2两个步骤,在 n 变成 0 之前,就能到所有的位。
参考代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cin >> n;
while (n)
{
cout << n % 10;
n /= 10;
}
return 0;
}
练习2:数位之和
cpp
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int ret = 0;
while (n)
{
ret += n % 10;
n /= 10;
}
cout << ret << endl;
return 0;
}
小提示:前面两个题目是相似的,当我们学会做一个题目的时候,要有举一反三的能力,要能将知识和思维迁移。
练习3:求和1
cpp
#include <iostream>
using namespace std;
int main() {
int n = 0;
cin >> n;
long long count = 0;
while(n)
{
count += n;
n--;
}
cout << count << endl;
return 0;
}
小提示:
注意数据范围,合理设置变量数据类型, 1 ⩽ n ⩽ 1 0 ∧ 9 1\leqslant{\mathsf{n}}\leqslant10^{\wedge}9 1⩽n⩽10∧9 ,那么求和的结果在int类型的变量中是无法保存的。
练习4:含 k 个 3 的数
cpp
#include <iostream>
using namespace std;
int main()
{
long long m = 0;
int k = 0;
int count = 0;
cin >> m >> k;
while(m)
{
if(m % 10 == 3)
{
count++;
}
m /= 10;
}
if(count == k)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
return 0;
}
小提示:
还是数据范围的问题,使用long long 类型是合适的。
练习5:角谷猜想
cpp
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
long long n = 0;
cin >> n;
while(n != 1)
{
if( n % 2 == 1)
{
printf("%lld*3+1=%lld\n", n ,n*3 + 1);
n = n*3 + 1;
}
else
{
printf("%lld/2=%lld\n", n, n/2);
n /= 2;
}
}
cout << "End" << endl;
return 0;
}
练习6:计算多项式的值
cpp
#include <cmath>
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
float x;
int n;
double sum = 1;
cin >> x >> n;
while(n)
{
sum += pow(x,n);
n--;
}
printf("%.2lf", sum);
return 0;
}
7. for循环
7.1 for循环语法形式
for 循环是三种循环中使用最多的, for 循环的语法形式如下:
bash
//形式1
for(表达式1; 表达式2; 表达式3)
语句;
//形式2
//如果循环体想包含更多的语句,可以加上
⼤括号
for(表达式1; 表达式2; 表达式3)
{
语句1;
语句2;
...
}
表达式1 用于循环变量的初始化;
表达式2 用于循环结束条件的判断;
表达式3 用于循环变量的调整 .
7.2 执行流程
for循环的执行流程
首先执行 表达式1 初始化循环变量,接下来就是执行 表达式2 的判断部分, 表达式2 的结果如果!=0,则循环结束; 表达式2 的结果如果! =0 则执行循环语句,循环语句执行完后,再去执行表达式3 ,调整循环变量,然后再去 表达式2 的地方执行判断, 表达式2 的结果是否为0,决定循环是否继续。
整个循环的过程中, 表达式1 初始化部分只被执行1次,剩下的就是 表达式2 、循环语句、 表达式3在循环。
7.3 实践
练习:使用 for 循环在屏幕上打印1~10的值
参考代码:
cpp
//代码1
#include <iostream>
using namespace std;
int main()
{
int i = 0;
for(i = 1; i <= 10; i++)
{
cout << i << " ";
}
return 0;
}
//代码2
#include <iostream>
using namespace std;
int main()
{
for(int i = 1; i <= 10; i++)
{
cout << i << " ";
}
return 0;
}
小提示:
上面两种代码的差异是,代码1中for循环结束后,i的值还可以继续使用;但是代码2中for循环的外边是不能使用的,i只能在for循环中使用。
7.4 while和for对比
for 和 while 在实现循环的过程中都有初始化、判断、调整这三个部分,但是for 循环的三个部分非常集中,便于代码的维护,而如果代码较多的时候while 循环的三个部分就比较分散,所以从形式上 for 循环要更优一些。
7.5 练习
练习1:求和2
计算 1 ∼ 100 \tt1\sim100 1∼100 之间3的倍数的数字之和
参考代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0;
int sum = 0;
for(i = 1; i <= 100; i++)
{
if(i % 3 == 0)
{
sum += i;
}
}
cout << sum << endl;
return 0;
}
练习2:求平均年龄
cpp
#include <iostream>
using namespace std;
int main()
{
int n = 0;
int t = 0;
int sum = 0;
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> t;
sum += t;
}
printf("%.2lf\n", sum * 1.0 / n);
return 0;
}
练习3:奥运奖牌计数
cpp
#include <iostream>
using namespace std;
int n, p1, p2, p3, sum, a, b, c;
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a >> b >> c;
p1 += a;
p2 += b;
p3 += c;
}
sum = p1 + p2 + p3;
cout << p1 << " " << p2 << " " << p3 << " "<< sum << endl;
return 0;
}
练习4:鸡尾酒疗法
cpp
#include <iostream>
using namespace std;
int n;
float x,y;
int a, b;
int main()
{
cin >> n;
cin >> a >> b;
x = b * 1.0 / a;
for(int i = 0; i < n - 1; i++)
{
cin >> a >> b;
y = b * 1.0 / a;
if (y - x > 0.05)
cout << "better" << endl;
else if (x - y > 0.05)
cout << "worse" << endl;
else
cout<< "same" << endl;
}
return 0;
}
练习5:救援
直角三角形求对角线的长度: z = S q r t ( x Λ 2 + y Λ 2 ) z={\mathsf{S q r t}}(\mathsf{x}^{\Lambda}2+\mathsf{y}^{\Lambda}2) z=Sqrt(xΛ2+yΛ2)
cpp
#include <cmath>
#include <iostream>
using namespace std;
int main()
{
int n, p;
cin >> n;
double a, b, t;
for(int i = 0; i < n; i++)
{
cin >> a >> b >> p;
double s = sqrt(a*a + b*b);
t += s / 50 + p * 1.0 + p * 0.5 + s / 50;
}
cout << (int)ceil(t) << endl;
return 0;
}
ceil 和 floor 函数
这里再给大家介绍2个函数: ceil 和 floor 函数ceil - 对一个浮点数向上取整,需要头文件 。
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
cout << ceil(2.3) << endl;
cout << ceil(3.8) << endl;
cout << ceil(-2.3) << endl;
cout << ceil(-3.8) << endl;
return 0;
}
输出结果:
bash
3
4
-2
-3
floor - 对一个浮点数向下取整,需要头文件
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
cout << floor(2.3) << endl;
cout << floor(3.8) << endl;
cout << floor(-2.3) << endl;
cout << floor(-3.8) << endl;
return 0;
}
输出结果:
bash
2
3
-3
-4
练习6:计算分数加减表达式的值
cpp
#include <iomanip>
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
double count = 0;
int flag = 1;
for(int i = 1 ; i <= n; i++)
{
count += 1.0 / i * flag;
flag = -flag;
}
cout << fixed << setprecision(4) <<count << endl;
return 0;
}
这个题目还有其他办法,自己可以多想想,然后动手是实现一下。
练习7:求分数序列和
cpp
#include <iostream>
using namespace std;
#include <iomanip>
int main()
{
double q1 = 2.0;
double p1 = 1.0;
int n;
cin >> n;
double count = 0;
for(int i = 1 ; i <= n; i++)
{
count += q1 / p1;
q1 = q1 + p1;
p1 = q1 - p1;
}
cout << fixed << setprecision(4) << count << endl;
return 0;
}
小提示:
这个题目要注意,要实现分数除法,除数和被除数中至少得有一个浮点数的,所以干脆就直接将变量定义为浮点数。
8. do-while 循环
8.1 do-while语法形式
在循环语句中 do while 语句的使用最少,它的语法如下:
cpp
//形式1
do
语句;
while( 表达式 );
//形式2
do
{
语句1;
语句2;
...
}
while( 表达式 );
while 和 for 这两种循环都是先判断,条件如果满足就进入循环,执行循环语句,如果不满足就跳出循环;
而 do while 循环则是先直接进入循环体,执行循环语句,然后再执行while 后的判断表达式,表达式为真,就会进行下一次,表达式为假,则不再继续循环。
8.2 执行流程
在 do while 循环中先执行图上的"语句",执行完语句,在去执行"判断表达式",判断表达式的结果是 : = 0 \mathrel{\mathop:}=0 :=0 ,则继续循环,执行循环语句;判断表达式的结果 = = 0 \mathtt{=}{}=0 ==0 ,则循环结束。
所以在 do while 语句中循环体是至少执行一次的,这是 do while 循环比较特殊的地方。
8.3 实践
使用 do while 循环在屏幕上打印 1 ∼ 10 \mathtt{1}{\sim}10 1∼10 的值
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 1;
do
{
cout << i << " ";
i = i + 1;
} while (i <= 10);
return 0;
}
一般 do while 使用在循环体至少被执行一次的场景下,所以较少一些。
8.4 练习
练习1:统计正整数的位数
输入一个正整数,计算这个整数是几位数?
例如:
输入:1234 输出:4
输入:12 输出:2
参考代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cin >> n;
int cnt = 0;
do
{
n = n / 10;
cnt++;
} while (n);
cout << cnt << endl;
return 0;
}
小提示:
这里并非必须使用 do while 语句,但是这个代码就比较适合使用 do while 循环,因为n即使是0,也是1位数,要统计位数的。
练习2:球弹跳高度的计算
这个题目最好是配合画图,能好理解一些。
将第一次落地独立出来,然后经过9组的反弹 + 落下,在这9次中每次反弹的高度就是下落的高度,第10次下落再独立出来。
下落和反弹的示意图 :
9组:反弹+ 下落
cpp
#include <iostream>
using namespace std;
int main()
{
double h = 0;
double total = 0;//总
cin >> h;
total += h;
int i = 1;
do
{
h /= 2;
total += h * 2;
i++;
}
while(i <= 9);
cout << total << endl;
cout << h/2 << endl;
return 0;
}
9. break和continue语句
9.1 break和continue介绍
• 在循环执行的过程中,如果某些状况发生的时候,需要提前终止循环,这是非常常见的现象。 C + + \mathsf{C}\substack{++} C++ 中提供了 break 和 continue 两个关键字,就是应该到循环中的。break 的作用是用于永久的终止循环,只要 break 被执行,直接就会跳出循环,继续往后执行。
• continue 的作用是跳过本次循环 continue 后边的代码,在 for 循环和 while 循环中有所差异的。
注意: break 和 continue 在各个循环语句中的使用方式基本相同,这里仅以 while 循环举例。
9.2 break举例
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
{
break; //当i等于5后,就执⾏break,循环就终⽌了
}
cout << i << " ";
i = i + 1;
}
return 0;
}
执行的结果:
打印了1,2,3,4后,当i等于5的时候,循环正 break 的地方终止,不再打印,不再循环。
所以 break 的作用就是永久的终止循环,只要 break 被执行, break 外的第一层循环就终止了。
那以后我们在循环中,想在某种条件下终止循环,则可以使用break 来完成我们想要的效果。
9.3 continue举例
continue 是继续的意思,在循环中的作用就是跳过本次循环中 continue 后边的代码,继续往下执行。
上面的代码,如果把 break 换成 continue 会是什么结果呢?
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 1;
while (i <= 10)
{
if (i == 5)
{
continue; //当i等于5后,就执⾏continue,本次循环就被跳过了
}
cout << i << " ";
i = i + 1;
}
return 0;
}
到这里我们就能分析出来, continue 可以帮助我们跳过某一次循环 continue 后边的代码,直接到循环的判断部分,进行下一次循环的判断,如果循环的调整是在continue 后边的话,可能会造成死循环。
如果在下面的for循环中使用continue呢?
cpp
#include <iostream>
using namespace std;
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
cout << i << " ";
}
return 0;
}
通过验证,我们发现这个代码输出的为:
cpp
1 2 3 4 6 7 8 9 10
在 for 循环中, continue 跳过本次循环中 continue 后边的代码,接下来执行的是i++ ,在这里循环变量得到了调整,就没有造成死循环,所以 continue 在 while 循环和 for 循环中略有差异。
9.4 练习
练习: 质因数分解
解析:
首先要了解什么是质数,质数是只能被 1 和它本身整除的数字,也就是质数只有 2 个因子,就是1 和它本身。
所以假设 n 有两个质数的因子,首先就是 n = m1 ⋆ m2 \textsf{n}=\textsf{m1}\star\textsf{m2} n=m1⋆m2 , m1 和 m2 是两个质数因子。
m1 和 m2 是质数的话,就说明没有除了 1 和它本身的因子,所以 n 的因子也只能是 1 、 m1 、m2 和 n ,所以我们只需要找出 2 ∼ n − 1 2\sim\boldsymbol{\mathsf{n}}-\boldsymbol{\mathsf{1}} 2∼n−1 (不包含 1 和 n \mathsf{n} n )之间较小的因子 m1 ,则 m 2 = n 1 m2={\textsf{n}}_{\mathit{1}} m2=n1 m1 。
参考代码:
cpp
#include <iostream>
using namespace std;
int main()
{
int n = 0;
int i = 2;
cin >> n;
while(i++ < n)
{
if(n % i == 0)
break;
}
cout << n/i << endl;
return 0;
}
10. 循环嵌套
10.1 循环嵌套的使用
前面学习了三种循环 while , do while , for ,这三种循环往往会嵌套在一起才能更好的解决问题,就是我们所说的:循环嵌套。这三种循环都可以任意嵌套使用,这里我们通过一个示例来了解循环嵌套。
比如:写一个代码,打印一个乘法口诀表,如下所示:
bash
1*1= 1
1*2= 2 2*2= 4
1*3= 3 2*3= 6 3*3= 9
1*4= 4 2*4= 8 3*4=12 4*4=16
1*5= 5 2*5=10 3*5=15 4*5=20 5*5=25
1*6= 6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7= 7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8= 8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9= 9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
让我们仔细分析一下:
- 我们首先研究一下这个打印的内容,我们发现打印的内容是分为9行的,第1行打印1项,第2行打印2项,第3行打印3项,以此类推,第9行打印9项。
- 如果观察每一行的信息,也能找到一些规律每一项的第一个乘数和列号是一致的,每一项的第二个乘数和行号是一致的,两个乘数的积就是第三个数。
- 打印9行,我们可以使用循环解决,总共循环9次,每次进入循环打印一行,循环变量使用 i 来控制, i 从1开始,循环到9,如下:
cpp
for(int i = 1; i <= 9; i++)
{
//打印⼀⾏的内容
}
- 那怎么打印一行呢?第 i 行是有 i 项组成的,这 i 项的打印也可以写成循环来完成。使用循环变量 j , j 从1开始,一致循环到 i ,正好循环 i 次,正好打印 i 项。同时每一行打印完后还要换行。
cpp
for(int i = 1; i <= 9; i++)
{
//打印⼀⾏的内容
for(int j = 1; i <= i; j++)
{
printf("%d*%d=%2d ", j, i, j * i);
}
printf("\n");
}
- 还有一个细节值得注意,输出的效果中,i*j的结果如果是2位数,才有右对齐,不够2位数的情况,使用空格补齐。所以这里就得使用 %2d 这样的输出格式控制了。
最终代码:
cpp
int main()
{
for(int i = 1; i <= 9; i++)
{
//打印一行的内容
for(int j = 1; j <= i; j++)
{
printf("%d*%d=%2d ", j, i, j * i);
}
printf("\n");
}
return 0;
}
正好一道OJ题目,来上手操练起来:
练习1:乘法表
cpp
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
for(int i = 1; i <= 9; i++)
{
//打印一行的内容
for(int j = 1; j <= i; j++)
{
printf("%d*%d=%2d ", j, i, j * i);
}
printf("\n");
}
return 0;
}
总结一下:
像题目要求的这种情况,就得使用两层循环嵌套来解决,外层循环负责控制打印几行,内部循环负责控制每一行打印几项。未来在写代码的过程中其实循嵌套使用会非常频繁,慢慢琢磨。
10.2 练习
练习1:包含数字9的数
cpp
#include <iostream>
using namespace std;
int main() {
int k = 9;
int n;
int count = 0;
while(k <= 2019)
{
n = k;
while(n)
{
if(n % 10 == 9)
{
count++;
break;
}
n = n / 10;
}
k++;
}
cout << count << endl;
return 0;
}
小提示:
在多层嵌套的循环中也可以使用break,但是要注意,一个break只能跳出自己所在的循环,无法一次性跳出所有的循环。
练习2:斐波那契数列
cpp
#include <iostream>
using namespace std;
int main()
{
int n = 0;
cin >> n;
for(int i = 0;i < n; i++)
{
int a1 = 1;
int a2 = 1;
int a3 = 1;
int k;
cin >> k;
while(k > 2)
{
a3 = a1 + a2;
a1 = a2;
a2 = a3;
k--;
}
cout << a3 << endl;
}
return 0;
}
练习3:求出 e 的值
cpp
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n = 0;
cin >> n;
int i = 1;
double e = 1;
while (i <= n)
{
int j = 0;
long long fac = 1;
for (j = 1; j <= i; j++)
{
fac *= j;
}
e += 1.0 / fac;
i++;
}
printf("%.10lf\n", e);
return 0;
}
练习4:三角形
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n = 0;
cin >> n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= i; j++)
cout << "*";
cout << endl;
}
return 0;
}
练习5: 画矩形
cpp
#include <iostream>
using namespace std;
int main()
{
int a, b, c;
char d;
cin >> a >> b >> d >> c;
if(c == 1)
{
for(int i = 0; i < a; i++)
{
int j = b;
while(j--)
{
cout << d;
}
cout << endl;
}
}
else
{
for(int i = 0; i < a ; i++)
{
for(int j = 0; j < b; j++)
{
if(i == 0 || i == a - 1 || j == 0 || j == b - 1)
{
cout << d;
}
else
{
cout << ' ';
}
}
cout << endl;
}
}
return 0;
}
如果我们仔细去琢磨上面的代码,会发现 if 和 else 中都是打印图案,区别在于实心还是空心,而实心和空心的区别又在于中间区域,其实边上的一圈实心和空心是一样的。所以我们在实现的时候,边上一圈打印字符,剩余的区域,做一个判断,如果是实心打印c,如果是空心就打印空格就好了,那么就有了下面简化的写法。
简化的写法:
cpp
#include <iostream>
using namespace std;
int main()
{
char c;
int a, b, f;
cin >> a >> b >> c >> f;
for (int i = 1; i <= a; i++)
{
for (int j = 1; j <= b; j++)
{
if (i == 1 || i == a || j == 1 || j == b)
cout << c;
else if (f == 0)
cout << ' ';
else
cout << c;
}
cout << endl;
}
return 0;
练习6:第 n 小的质数
解析:
-
质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数。
-
第n小的质数,其实就是从小到大的第n个质数。
思路:
1.输入n;
2.从2开始向后,找到n个质数,第n个质数就是第n个小的质数:
cppint i = 2; int cnt = 0; while(1) { //判断i是否是素数, //试除:拿2~i-1之间的数去试; //如果有一个数可以整除,那不是素数,反之,是; //如果是素数:i++; if(cnt == n) break; i++; }
cpp
#include <iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int i = 2;
int cnt = 0;//计数
while(1)
{
//判断是否为素数
int flag = 1; //假设i是素数
for(int j = 2; j <= i-1; j++)
{
if(i % j == 0)
{
flag = 0;
break;
}
}
if(flag == 1)
{
cnt++;
}
if (cnt == n)
{
break;
}
i++;
}
cout << i << endl;
return 0;
}
上面的代码如果直接提交,会出现超时的问题,如下图:
测试点信息
"Time Limit Exceeded"(TLE,超时)是一个在编程竞赛和在线评测平台(如LeetCode、Codeforces、HackerRank等)中常见的错误信息。它意味着程序在执行过程中超过了给定的最大运行时间限制,而未能在规定时间内得出结果。
优化思路:如果 n 有⼀个因⼦ a ,那么必然存在另⼀个因⼦ b ,使得 n = a × b 。 。如果 a 和b 都大于 n \sqrt{n} n ,那么 a × b \mathsf{a}\times\mathsf{b} a×b 将会大于 n ,这与 n = a × b \mathsf{n}{=}\mathsf{a}\times\mathsf{b} n=a×b 矛盾。因此至少有一个因子不会超过 n \sqrt{n} n 的。
cpp
#include <iostream>
using namespace std;
#include <cmath>
int main()
{
int n;
cin >> n;
int i = 2;
int cnt = 0;//计数
while(1)
{
//判断是否为素数
int flag = 1; //假设i是素数
for(int j = 2; j <= sqrt(i); j++)//优化
{
if(i % j == 0)
{
flag = 0;
break;
}
}
if(flag == 1)
{
cnt++;
}
if (cnt == n)
{
break;
}
i++;
}
cout << i << endl;
return 0;
}
这样就可以完美通过:
练习7:水仙花数
cpp
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
for(int i=100; i<= 999; i++)
{
int tmp = i;
int ret = 0;
while(tmp)
{
ret += pow(tmp % 10, 3);
tmp /= 10;
}
if(ret == i)
cout << i << endl;
}
return 0;
}
这里大家可以学习一下 pow 函数,可以用计算次方的函数, pow(x, y) 返回的是 × \times × 的 y 次方的值。
pow 函数需要一个头文件 <cmath>
完
总结
通过练习题的实践,读者能够更好地理解条件判断和循环控制在程序中的重要性,并掌握如何根据不同的需求选择合适的语句或操作符。无论是简单的条件分支,还是复杂的循环嵌套,本章的内容都为读者提供了坚实的理论基础和实用的操作技巧。