要求:
程序输入的一个小于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++ 的关键字, <条件表达式>
是循环控制条件,<条件表达式>
后面的语句是循环体。
while 语句执行过程
首先计算<条件表达式>
的值,如果<条件表达式>
的值为0(即 false ),则跳过循环体<语句>
,执行整个 while 语句的后继语句;
如果<条件表达式>
的值为非0(即 true ),则执行指定的<语句>
,执行完该语句后,再计算<条件表达式>
的值,如果<条件表达式>
的值仍然为非0,则继续执行指定的<语句>
,再进行测试 ……,直到<条件表达式>
的值为0,再跳过循环体<语句>
,结束整个 while 语句的执行,接着执行整个 while 语句的后继语句。
执行流程图如下:
例如下面的程序可以计算飞机上下落的铁球落地的时间(精确到秒)。假设飞机高度为2500米,下落的高度d(米)和时间t(秒)之间的关系是d=(1/2)gt ^ 2
, 其中g = 9.82 m/s ^ 2
。
// 初始状态时间为秒,下落高度为米
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 语句的循环体。
<初始化语句>
可以是任何合法的语句,<条件表达式>
和<增量表达式>
则可以由任何合法的表达式充当,具体说明如下:
1.初始化语句:
<初始化语句>通常是一个赋值语句,用来给循环控制变量赋初值。
<初始化语句>可以是表达式语句或声明语句,以“ ; ”结束。
2.条件表达式:
<条件表达式>是一个能够转换成逻辑值的表达式,它决定什么时候退出循环,该表达式可以为空(为空时逻辑值恒为 true )。
<条件表达式>和<增量表达式>之间用 “ ; ” 分开。
3.增量表达式:
<增量表达式>定义了循环控制变量每循环一次后按什么方式变化,该表达式也可以为空,这时不产生任何计算效果。
for 语句的执行过程
首先计算<初始化语句>
,然后计算<条件表达式>
的值。
如果该值为 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;
编程要求
获取输入的一个小于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
int main()
{
int n;
int h, l;
int max, mid, min;
int i = 0;
cin >> n;
while(n != 495)
{
int a = n / 100;
int b = n / 10 % 10;
int c = n % 10;
if (a <= b)
{
if (c >= b)
{
mid = b;
max = c;
min = a;
}
else if (c >= a)
{
mid = c;
max = b;
min = a;
}
else
{
mid = a;
max = b;
min = c;
}
}
else
{
if (c < b)
{
mid = b;
max = a;
min = b;
}
else if(c < a)
{
mid = c;
max = a;
min = b;
}
else if (c > a)
{
mid = a;
max = c;
min = b;
}
}
h = max * 100 + mid * 10 + min;
l = min * 100 + mid * 10 + max;
i ++;
n = h - l;
std::cout << i << ":" << h << "-" << l << "=" << n << std::endl;
}
return 0;
}
测试编译为: