100
任务描述
本关任务:输入一个年份,判断该年份是否是闰年,是闰年则输出 Yes,否则输出 No。
相关知识
编程时有时候需要根据某个条件是否满足来选择执行或不执行某些语句。
C 和 C++ 的 if 语句可以实现这种根据条件判断来选择执行的功能。if 语句有两种形式,分别实现一路分支和两路分支。
if 语句
实现一路分支的基本方法是采用 if 语句:
if (<条件表达式>) <语句>
其语义为:如果<条件表达式>
的值为非0 ( true ),即“真”,则执行<语句>
,然后按顺序执行 if 语句的后继语句。如果<条件表达式>
的值为0( false ),即“假”,则忽略<语句>
,按顺序执行 if 语句的后继语句。
例如:
// 当分数 score 小于 60 时,执行输出语句,否则跳过该语句(不执行)
if (score < 60)
cout << "Sorry, you've failed!\n";
if...else 语句
实现两路分支的常用方法是采用 if...else 语句:
if (<条件表达式>) <语句1>
else <语句2>
其中,else 和<语句2>
称为 else 分支或 else 子句。
其执行语义为:如果<条件表达式>
的值为非0,即“真”( true ),则执行<语句1>
,执行完<语句1>
后继续执行整个 if 语句的后继语句(不执行<语句2>
);如果<条件表达式>
的值为0,即“假”( false ),则跳过<语句 1>
,执行<语句2>
,执行完<语句2>
后继续执行整个 if 语句的后继语句。
即 if 语句是根据<条件表达式>
的结果,选择<语句1>
和<语句2>
中的一个执行,执行完后,整个 if 语句也就执行完了。
例如:
// 当分数 score 大于等于 60 时输出"Passed",否则输出"Failed"
if (grade >= 60)
cout << ″Passed\n″;
else
cout << ″Failed\n″;
if 语句的分支有且只能有一条语句,如果某个分支不需要做任何事时,可以使用空语句,空语句就是一个独立的分号。如果需要做很多事,一条语句完成不了,可以使用复合语句。用花括号括起来的一条或者多条语句叫复合语句,复合语句可以当做一条语句来看。
例1:
// 当速度 speed 小于等于 120 时什么也不做,否则输出"危险驾驶"
if (speed <= 120)
;// 空语句
else
cout<<"危险驾驶"<
例2:
// 如果 a 大于 b 则交换 a、b 的值
if (a > b)
{
// 复合语句
int c = a;
a = b;
b = c;
}
C 和 C++ 中任何有值的表达式都可以作为条件表达式(计算结果非0则为真,0则为假)。如果需要综合判断多个条件,就需要使用逻辑运算符了。
例如如果要描述条件“分数 x 在0到100之间”,不能使用数学中的表达形式0 <= x <= 100
,而应当使用逻辑运算符x >= 0 && x <= 100
。
// 逻辑与 && 表示两个条件x >= 0 和 x <= 100 都为真,结果才为真
if (x >= 0 && x <= 100)
……
直接写成0 <= x <= 100
编译器也不会报错,但语义完全不一样:
// 表示先计算 0 <= x ,结果可能是 true 或者 false,然后用该结果和 100 比较,所以该条件永远为真
if (0 <= x <= 100)
……
编程要求
在右侧编辑器中的Begin-End
之间补充代码,判断输入的年份(输入数据由平台提供,需要你获取后再使用)是否位闰年,是则输出 Yes,否则输出 No。
提示:闰年的判别条件是该年年份能被 4 整除但不能被 100 整除、或者能被 400 整除。闰年的 2 月有 29 天,其它月份的天数和非闰年是一样的。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:2017
预期输出:No
测试输入:2000
预期输出:Yes
开始你的任务吧,祝你成功!
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int main()
{
int year;
// 请在此添加代码,判断输入的年份是否位闰年,是则输出"Yes",否则输出"No"
/********** Begin *********/
scanf("%d",&year);
if((year%4==0&&year%100!=0)||year%400==0){
printf("Yes");
}else{
printf("No");
}
/********** End **********/
return 0;
}
100
任务描述
本关任务:输入一个日期,如“ 2017 6 15 ”,计算这一天是这一年的第几天(1月1日是第一天)并输出。假设输入的都是合法的日期,但别忘了考虑闰年的情况。
相关知识
if 语句回根据对某个条件的判断结果,将程序的流程分为两支。而本关将要介绍的是会将程序分为多个分支的语句:
if-else 嵌套
switch 语句
下面我们就一起来学习这两种语句的使用。
if-else 嵌套
多路分支的第一种实现方法就是使用 if-else 嵌套,即在 if 分支和(或者) else 分支中再嵌套 if-else 语句。
例如:
cin >> angle; // 输入角度
if (angle % 90 == 0)
{
// if-else嵌套
if (angle % 180 == 0)
cout << "线段在X轴上" << endl;
else
cout << "线段在Y轴上" << endl;
}
else
cout << "线段在象限" << angle / 90 + 1 << endl;
该程序计算输入的角度 angle 落在哪个象限或者哪个轴上。当输入的角度是90的倍数时(angle % 90 == 0
为真),有两种情况,或者在X轴上,或者在Y轴上,所以需要其它条件(angle % 180 == 0
)再次判断进行区分处理。
上面程序通过 if-else 嵌套实现了三路分支。
switch 语句
另一种实现多路分支的方法是使用 switch 语句, 格式如下:
switch(<条件表达式>)
{
case <常量表达式1>:
<语句序列1>;
case <常量表达式2>:
<语句序列2>;
……
case <常量表达式n>:
<语句序列n>;
default:
<语句序列n+1>;
}
其中,switch 、case 和 default 都是 C++ 的关键字。<条件表达式>
是值为整型的表达式;每个 case 对应一个分支处理;default 分支为默认处理分支;<常量表达式1>
……<常量表达式n>
都是值为整型常量的表达式;<语句序列1>
……<语句序列n+1>
都是一组语句,可以为空。
执行流程
switch 语句执行流程如下:
switch 语句执行时,首先计算<条件表达式>
得到一个整型的值,将该值与<常量表达式1>
……<常量表达式n>
的值逐个进行比较,如果与其中一个相等,则执行该常量表达式下的语句序列。
需要注意的是执行完该常量表达式对应的语句序列后,还将继续执行后续分支的处理语句序列,直到 switch 语句结束或者遇到跳转指令(break);如果测试表达式的值不与任何一个常量表达式的值相等,则执行 default 分支后面的语句。
流程图如下:
switch 语句与 break
当一个 case 分支条件得到满足时,执行完该分支的语句序列后,还将继续执行后续分支的处理语句序列。如果希望执行完一个分支后就结束整个 switch 语句,可以在每个分支语句后面都加上一条 break 语句。
break 语句是一种转移语句,只能出现在 switch 结构和循环结构中。break 语句可以跳出直接包含该 break 语句的 switch 结构或循环结构(只能跳出一层),程序控制离开该 switch 结构或循环结构,执行其后继语句。
带 break 语句的 switch 语句模式如下:
switch(<条件表达式>)
{
case <常量表达式1>:
<语句序列1>;
break;
case <常量表达式2>:
<语句序列2>;
break;
……
case <常量表达式n>:
<语句序列n>;
break;
default:
<语句序列n+1>;
}
其执行过程为:首先计算<条件表达式>
,将得到的整型值与<常量表达式1>
……<常量表达式n>
的值逐个进行比较,一旦检测到与其中一个相等,则执行该常量表达式下的语句序列,执行完后,紧接着就执行 break 语句,离开该 switch 结构,不再执行后续分支的处理语句序列,转向执行整个 switch 语句的后继语句。
例如下面的程序将百分制转换成十分制输出。如输入85,计算 scorePhrase 为8,则执行 switch 语句后进入case 8:
分支,输出‘B’,然后执行 break ;语句跳出整个 switch 语句:
cin >> score; // 输入百分制分数
scorePhrase = score / 10; // 计算分数段,转换成十分制
// 判断并输出等级
switch (scorePhrase)
{
case 10:
case 9:
cout << 'A' << endl;
break;
case 8:
cout << 'B' << endl;
break;
case 7:
cout << 'C' << endl;
break;
case 6:
cout << 'D' << endl;
break;
case 0: case 1: case 2: case 3: case 4: case 5:
cout << 'E' << endl;
break;
default:
cout << "The score is illegal!" << endl;
}
编程要求
在右侧编辑器中的Begin-End
之间补充代码,通过输入的日期(数据由平台提供,以“年 月 日”的形式表示,需要你获取后使用)来判断该天是当年的第几天的要求。具体要求如下:
对于输入一个日期(年月日之间以一个空格间隔),形如2017 6 15
,计算这一天是这一年的第几天并输出;
输出形式为“年-月-日是第X天”(其中 X 是你的计算结果)。
提示:本题计算思路比较清晰,例如 6 月 15 日就需要把前 5 个月的天数全部加上再加上 15 , 5 月 3 日则只需要加满前四个月的天数再加上 3 ,所以本题的计算根据月份不同而方法不同。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试: 平台会对你选择的答案进行判断,全对则通过测试:
测试输入:2017 6 15
预期输出:2017-6-15是第166天
测试输入:2000 10 1
预期输出:2000-10-1是第275天
开始你的任务吧,祝你成功!
年轻,是明明犯了错,却被原谅了。年老,是明明没犯错,却被挑出了错。上天偏爱年轻人,让他享有重新来过的权利。
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int main()
{
// y-年,m-月,d-日,n-第几天
int y, m, d, n;
// 请在此添加代码,计算并输出指定日期是第几天
/********** Begin *********/
scanf("%d%d%d",&y,&m,&d);
n=d;
switch(m){
case 12:n+=30;
case 11:n+=31;
case 10:n+=30;
case 9:n+=31;
case 8:n+=31;
case 7:n+=30;
case 6:n+=31;
case 5:n+=30;
case 4:n+=31;
case 3:
if((y%4==0&&y%100!=0)||y%400==0){
n+=29;
}else{
n+=28;
}
case 2:n+=31;
case 1:;
}
/********** End **********/
printf("%d-%d-%d是第%d天\n",y,m,d,n);
return 0;
}
200
任务描述
本关任务:输入一个1000(不包含1000)以内的正整数,首先将其补齐为三个数字(如果是两位数或者一位数,则前面补0),然后将这三个数字按不同顺序排列成一组数据,输出排列中最大的那个数。
例如:
如果输入249,可以重排出429,249,924,942等等,其中最大的应该是942,因此应输出942;
如果输入的是14,则在前面补0得到014,据此可以重排出041,140,410等等,其中最大的应该是410,因此应输出410。
相关知识
完成本关需要具备的知识介绍请参见第一、二关卡。
编程要求
在右侧编辑器中的Begin-End
之间补充代码,将输入的1000(不包含1000,且数据由平台提供,需要你获取后使用)以内的正整数的三个数字(如果是两位数或者一位数,则前面补0)进行重排,得到最大的数并输出。
提示
要得到一个三位数的某个数字可以使用求余运算和除法运算。例如下面的程序可以获取一个三位数的十位数并输出:
int num = 258;
int a = num / 10 % 10;
cout << a;
第二条语句先计算num /10
得到25,然后用25对10求余得到5,程序最后输出5。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:5
预期输出:500
测试输入:185
预期输出:851
开始你的任务吧,祝你成功!
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int main()
{
// n-输入的数,m-重排后的数
int n, m;
// 请在此添加代码,输入一个小于1000的正整数,重排出最大的数存入m中
/********** Begin *********/
cin>>n;
int a,b,c,max,mid,min;
a=n/100;
b=n/10%10;
c=n%10;
if(a<=b){
if(c>=b){
max=c;
mid=b;
min=a;
}else if(c>=a){
max=b;
mid=c;
min=a;
}else{
max=b;
mid=a;
min=c;
}
}else if(b>=c){
max=a;
mid=b;
min=c;
}else if(a>=c){
max=a;
mid=c;
min=b;
}else{
max=c;
mid=a;
min=b;
}
m=max*100+mid*10+min;
/********** End **********/
// 输出重排后的数
cout << m << endl;
return 0;
}
200
任务描述
本关任务:程序输入的一个小于1000且三个数字不全相等的整数,请你输出进入黑洞的重排求差过程。本问题又称“Kaprekar问题”。
495是一个很神奇的数,被称为黑洞数或者陷阱数。
给定任何一个小于1000的正整数,经前位补0后可以得到一个三位数(两位数前面补1个0,一位数前面补2个0)。如果这个三位数的三个数字不全相等,那么经有限次“重排求差”操作(组成该数的数字重排后的最大数减去重排后的最小数),总会得到495。
例如,对整数80,前位补0后得到080,重排后可以得到800,008。此时可以得到的最大数为800,最小数为008(即8)。那么只需要4次重排求差即可得到495,过程如下:
1:800-8=792 //第一次
2:972-279=693 //第二次,将第一次的结果进行重排求差
3:963-369=594 //第三次,将第二次的结果进行重排求差
4:954-459=495 //第四次以此类推
相关知识
要实现上述功能,需要反复做一些相同或相似的工作,也就是反复执行一些代码。这需要用到循环语句。
C 和 C++ 有3种基本的循环控制结构:while 语句、do-while 语句和 for 语句。
while 循环
while 循环语句表现为:
while (<条件表达式>)
<语句>
其中 while 是 C 和 C++ 的关键字, <条件表达式>
是循环控制条件,<条件表达式>
后面的语句是循环体。
首先计算<条件表达式>
的值,如果<条件表达式>
的值为0(即 false ),则跳过循环体<语句>
,执行整个 while 语句的后继语句;
如果<条件表达式>
的值为非0(即 true ),则执行指定的<语句>
,执行完该语句后,再计算<条件表达式>
的值,如果<条件表达式>
的值仍然为非0,则继续执行指定的<语句>
,再进行测试 ……,直到<条件表达式>
的值为0,再跳过循环体<语句>
,结束整个 while 语句的执行,接着执行整个 while 语句的后继语句。
执行流程图如下:
例如下面的程序可以计算飞机上下落的铁球落地的时间(精确到秒)。假设飞机高度为2500米,下落的高度d(米)和时间t(秒)之间的关系是d=(1/2)gt2,其中g=9.82m/s2:
// 初始状态时间为秒,下落高度为米
int sec = 0;
float dis = 0;
// 如果下落高度小于米,则继续循环
while (dis < 2500)
{
// 每次循环计算每秒后的下落高度
sec += 1;
dis = 0.5 * 9.82 * sec * sec;
}
// 输出落地需要的秒数
cout << sec << "秒" << endl;
do-while 语句
第二种循环语句是 do-while 语句,一般格式为:
do <语句>
while (<条件表达式>);
其中,do 和 while 都是 C 和 C++ 的关键字,do 和 while 之间的语句是循环体,<条件表达式>
是循环控制条件,整个 do-while 语句的最后是作为语句结束标志的分号。
do-while 语句构成的循环与 while 语句构成的循环有所不同: 它 先执行循环中的<语句>
,然后计算<条件表达式>
的值,判断条件的真假,如果为 true,则继续循环;如果为 false,则终止循环,继续执行整个 do-while 语句的后继语句。
因此,do-while 语句是一种出口控制的循环结构,其循环体至少要被执行一次,而 while 语句是入口控制的循环结构,其循环体未必会被执行。
do-while 语句的执行流程图如下:
同样的,当循环体包含多条语句时,可以用花括号把它们括起来,形成一个复合语句。
for 语句
第三种循环语句为 for 语句,一般形式为:
for (<初始化语句> ;[<条件表达式>]; [<增量表达式>] )
<语句>
for 是 C 和 C++ 的关键字,表示 for 循环语句的开始。<语句>
是 for 语句的循环体。
<初始化语句>
可以是任何合法的语句,<条件表达式>
和<增量表达式>
则可以由任何合法的表达式充当,具体说明如下:
<初始化语句>
通常是一个赋值语句,用来给循环控制变量赋初值。<初始化语句>
可以是表达式语句或声明语句,以“ ; ”结束。
<条件表达式>
是一个能够转换成逻辑值的表达式,它决定什么时候退出循环,该表达式可以为空(为空时逻辑值恒为 true )。<条件表达式>
和<增量表达式>
之间用“ ; ”分开。
<增量表达式>
定义了循环控制变量每循环一次后按什么方式变化,该表达式也可以为空,这时不产生任何计算效果。
首先计算<初始化语句>
,然后计算<条件表达式>
的值。
如果该值为 false,则结束循环,跳过循环体的<语句>
,转到整个for
语句的后继语句继续执行;
如果该值为 true,则执行循环体的<语句>
,执行完循环体后,紧接着执行<增量表达式>
,再计算<条件表达式>
的值,如果该值为 true,则执行循环体的<语句>
,再执行<增量表达式>
,再计算<条件表达式>
进行测试,…… ,直到<条件表达式>
的值为 false,则结束循环,跳过循环体的<语句>
,继续执行整个 for 语句的后继语句。
for 语句的执行流程图如下:
例如下面的程序可以计算1到100之间所有整数的和并输出:
int sum = 0; // 声明求和变量并初始化
// 求和
for (int i = 1; i <= 100; i++)
sum += i;
cout << "The sum of 1 to 100 is: " << sum << endl;
编程要求
在右侧编辑器中的Begin-End
之间补充代码,获取输入的一个小于1000且三个数字不全相等的整数(数据由平台提供,你需获取后使用),并输出进入黑洞的重排求差过程。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:123
预期输出: 1:321-123=198
2:981-189=792
3:972-279=693
4:963-369=594
5:954-459=495
测试输入:18
预期输出: 1:810-18=792
2:972-279=693
3:963-369=594
4:954-459=495
开始你的任务吧,祝你成功!
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int Max(int num){
int m,n;
n=num;
int a,b,c,max,min,mid;
a=n/100;
b=n/10%10;
c=n%10;
if(a<=b){
if(c>=b){
max=c;
mid=b;
min=a;
}else if(c>=a){
max=b;
mid=c;
min=a;
}else{
max=b;
mid=a;
min=c;
}
}else if(b>=c){
max=a;
mid=b;
min=c;
}else if(a>=c){
max=a;
mid=c;
min=b;
}else{
max=c;
mid=a;
min=b;
}
m=max*100+mid*10+min;
return m;
}
int Min(int num){
int n,m;
n=num;
int a,b,c,max,mid,min;
a=n/100;
b=n/10%10;
c=n%10;
if(a<=b){
if(c>=b){
max=c;
mid=b;
min=a;
}else if(c>=a){
max=b;
mid=c;
min=a;
}else{
max=b;
mid=a;
min=c;
}
}else if(b>=c){
max=a;
mid=b;
min=c;
}else if(a>=c){
max=a;
mid=c;
min=b;
}else{
max=c;
mid=a;
min=b;
}
m=min*100+mid*10+max;
return m;
}
int main()
{
int n;
// 请在此添加代码,输出整数进入黑洞过程
/********** Begin *********/
cin>>n;
int i=1;
do{
printf("%d:%d-%d=%d\n",i,Max(n),Min(n),Max(n)-Min(n));
i++;
n=Max(n)-Min(n);
}while(n!=495);
/********** End **********/
return 0;
}
100
任务描述
本关任务:向程序输入一个正整数,请你判断该正整数是否是素数,如果是,则输出 Yes,否则输出 No。
相关知识
完成本关需要具备的知识介绍请参见第四关卡,本关介绍一下素数及其运用。
素数
素数,又称质数,是指在大于1的自然数中,除了1和它本身以外不能被其它数整除的数。最小的素数是2。
素数由于其不能被等分的原因,有很多实际的应用,例如:
汽车变速箱的齿轮的相邻的两个大小齿轮齿数一般设计为素数,以增加两齿轮内两个相同的齿相遇啮合次数的最小公倍数,可增强耐用度减少故障;
在害虫的生物生长周期和杀虫剂使用之间的关系上,实验表明,素数次数地使用杀虫剂是最合理的,都是使用在害虫繁殖的高潮期,而且害虫很难产生抗药性;
以素数形式无规律变化的导弹和鱼雷可以使敌人不易拦截等等。
编程要求
在右侧编辑器中的Begin-End
之间补充代码,判断输入的正整数(数据由平台提供,你需要获取后使用)是否为素数,如果是,则输出 Yes,否则输出 No。
注意:程序保证输入的正确性,即输入的 n 为正整数。
提示
本关需要用到循环控制结构来解决。如果输入的整数保存在变量 k 中,则需要尝试一些数能否被 k 整除,并根据结果判断 k 是否是素数。需要测试的数据可以是从 2 到k-1
,或者从 2 到k/2
,或者从 2 到开根号 k 也可以。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:2
预期输出:Yes
测试输入:987
预期输出:No
开始你的任务吧,祝你成功!
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int main()
{
int n;
int i,isPrime=1;;
// 请在此添加代码,输入正整数n,如果n是素数则输出“Yes”,否则输出“No”
/********** Begin *********/
scanf("%d",&n);
for(i=2;i
200
任务描述
本关任务:输入 n(10≤ n ≤10000) 和 k(1≤ k ≤10),求 n 以内最大的 k 个素数,按降序排列并将和输出在最后。
相关知识
完成本关需要具备的知识介绍请参见第四关卡。
编程要求
在右侧编辑器中的Begin-End
之间补充代码,输入正整数 n 和 k(数据由平台提供,n 与 k 之间用一个空格隔开,你需要获取后使用),要求输出 n 以内最大的前 k 个素数,按降序排列并在最后输出它们的和。
提示
本关需要用到循环控制结构来解决。素数范围是 2 到 n,因为要从大到小输出素数,所以可以从 n 循环到 2 ,使用 for 语句递减循环实现为:
for (int i = n; i>=2; i--)
……
第一次进入循环时 i 的值为 n,每次循环结束后 i 的值减1,再次进入循环,…… ,最后一次进入循环时 i 的值为2,之后再次减1后 i 的值为1,循环条件不满足退出循环。
循环体中则使用上一关的方法判断 i 是否是素数,是则输出、计数并计算累加和。
但该循环有可能不会循环到 i 为2,因为循环过程中可能已经找到了 k 个素数,这时就需要提前结束循环。根据条件提前结束循环可以使用 break 语句。如果素数计数变量为 m,则对应的语句为:
if(m == k)
break;
在每次找到一个素数,并计数后执行上述语句,如果 m 的值等于 k,则已经找到 k 个素数,就执行 break 语句,该语句的作用是跳出直接包含该语句的 switch 语句或循环语句。
测试说明
平台会对你编写的代码进行测试,比对你输出的数值与实际正确数值,只有所有数据全部计算正确才能通过测试:
测试输入:9994 7
预期输出:9973 9967 9949 9941 9931 9929 9923 69613
测试输入:13 9
预期输出:13 11 7 5 3 2 41
开始你的任务吧,祝你成功!
// 包含两种I/O库,可以使用任一种输入输出方式
#include
#include
using namespace std;
int main()
{
int n, k;
// 请在此添加代码,输入n和k,并输出n以内k个素数以及它们的和
/********** Begin *********/
scanf("%d %d",&n,&k);
int i,j,sum=0,a[10],s=0,isPrime=1;
for(i=n;i>1;i--){
isPrime=1;
for(j=2;j