个人主页:mzwang.top
数字黑洞
题目描述:
给定任一个各位数字不完全相同的 4 位正整数,如果我们先把 4 个数字按非递增排序,再按非递减排序,然后用第 1 个数字减第 2 个数字,将得到一个新的数字。一直重复这样做,我们很快会停在有“数字黑洞”之称的
6174
,这个神奇的数字也叫 Kaprekar 常数。
例如,我们从6767
开始,将得到7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174 7641 - 1467 = 6174 ... ...
现给定任意 4 位正整数,请编写程序演示到达黑洞的过程。
输入格式:
输入给出一个 (0,10^4 ) 区间内的正整数 N。
输出格式:
如果 N 的 4 位数字全相等,则在一行内输出
N - N = 0000
;否则将计算的每一步在一行内输出,直到6174
作为差出现,输出格式见样例。注意每个数字按4
位数格式输出。输入样例1:
6767
输出样例1:
7766 - 6677 = 1089 9810 - 0189 = 9621 9621 - 1269 = 8352 8532 - 2358 = 6174
输入样例2:
2222
输出样例2:
2222 - 2222 = 0000
题目来源:PAT乙级1019
作者:CHEN, Yue
单位:浙江大学
问题解决:
解题思想
设置num[]数组存放四位数的各位数字,num[3]存放千位,num[0]存放个位;提取出n的各位数字之后,采用C++标准库函数sort()对四位数字分别进行升序和降序的排序(注意sort()函数默认是按升序排序,降序排序时需要自行设置cmp_desc()函数以实现降序排序),然后将排序后的各位数字再次分别合成升序四位数asc和降序四位数des;最后按照四位数格式输出运算过程中的各整数。特别需要注意以下几点:
- 题目中已经说明n一定是正整数,因此输入的n不会是0(第一次不会因此退出循环而导致无输出),但n可能为
6174
,若n的输入为6174
时,需要进入循环输出一次再退出循环,此处我用flag标记控制。(注:PAT评测系统是有一个测试点输入为6174
的,若不特殊处理将导致此测试点不通过比如若将代码中while循环的条件改为下面的情况将产生部分错误)
while(n != 0&&n != 6174)
- 注意题目要求按四位格式输出整数,因此需要控制整数的输出。若在计算过程中asc或者des或者n出现三位数以下的情况(比如0189),输出的高位要补0。
代码示例(C/C++)
小提示:请将以下代码保存为.cpp
格式(C++程序)左右滑动代码可查看全部内容
#include <cstdio>
#include <algorithm>
using namespace std;
void Print_num(int m);
bool cmp_desc(int a,int b)
{
return a > b;
}
int main()
{
int n,num[4];//num[]数组存放四位数的各位数字,num[3]存放千位,num[0]存放个位
scanf("%d",&n);
int flag = 1;//标记是否是第一次输入了6174,若是,则需要进入一次循环
while(n != 0&&(n != 6174||flag)){//注意外面两条件之间是&&而非||
flag = 0;//进入循环后,以后再出现n为0或6174的情况,均退出循环
for(int i = 0; i < 4; i++){
num[i] = n % 10;
n /= 10;
}//提取出n的各位数
sort(num,num + 4);//升序排序
int asc = num[0] + num[1] * 10 + num[2] * 100 + num[3] * 1000;//重新合成四位数
sort(num,num + 4,cmp_desc);//降序排序
int des = num[0] + num[1] * 10 + num[2] * 100 + num[3] * 1000;//重新合成四位数
n = asc - des;
Print_num(asc);
printf(" - ");
Print_num(des);
printf(" = ");
Print_num(n);
printf("\n");
}
return 0;
}
//按四位数格式输出整数m
void Print_num(int m)
{
int j = 1000;
for(int i = 0; i < 4; i++){
printf("%d",m / j);
m %= j;
j /=10;
}
}