L2-029 特立独行的幸福 (25分)
对一个十进制数的各位数字做一次平方和,称作一次迭代。如果一个十进制数能通过若干次迭代得到 1,就称该数为幸福数。1 是一个幸福数。此外,例如 19 经过 1 次迭代得到 82,2 次迭代后得到 68,3 次迭代后得到 100,最后得到 1。则 19 就是幸福数。显然,在一个幸福数迭代到 1 的过程中经过的数字都是幸福数,它们的幸福是依附于初始数字的。例如 82、68、100 的幸福是依附于 19 的。而一个特立独行的幸福数,是在一个有限的区间内不依附于任何其它数字的;其独立性就是依附于它的的幸福数的个数。如果这个数还是个素数,则其独立性加倍。例如 19 在区间[1, 100] 内就是一个特立独行的幸福数,其独立性为 2×4=8。
另一方面,如果一个大于1的数字经过数次迭代后进入了死循环,那这个数就不幸福。例如 29 迭代得到 85、89、145、42、20、4、16、37、58、89、…… 可见 89 到 58 形成了死循环,所以 29 就不幸福。
本题就要求你编写程序,列出给定区间内的所有特立独行的幸福数和它的独立性。
输入格式:
输入在第一行给出闭区间的两个端点:1<A<B≤10
4
。
输出格式:
按递增顺序列出给定闭区间 [A,B] 内的所有特立独行的幸福数和它的独立性。每对数字占一行,数字间以 1 个空格分隔。
如果区间内没有幸福数,则在一行中输出 SAD。
输入样例 1:
10 40
输出样例 1:
19 8
23 6
28 3
31 4
32 3
注意:样例中,10、13 也都是幸福数,但它们分别依附于其他数字(如 23、31 等等),所以不输出。其它数字虽然其实也依附于其它幸福数,但因为那些数字不在给定区间 [10, 40] 内,所以它们在给定区间内是特立独行的幸福数。
输入样例 2:
110 120
输出样例 2:
SAD
//对于每一个给出的数A,对其迭代直至出现幸福数,死循环数、1或出现死循环
//若迭代至1,把从A开始迭代的所有数标记为幸福数,把A设为特立独行的数,并为所有数设置独立性
//若迭代至出现幸福数B,把由A开始迭代至B的所有数标记为幸福数,为它们设置独立性,把A设为特立独行的数,此时,B显然不会是特立独行的数(B依附于A)
//特别地,当A就是B时,不将A设为特立独行的数,因为此时不能判断A是否依附于给定范围内的其它数
//若迭代至出现死循环数C,把由A开始迭代至C的所有数标记为死循环数
//若迭代至出现死循环,如A->D->E->...->D,把A至第二个D的所有数标记为死循环数
#include<stdio.h>
#include<math.h>
bool IsPrime(int x)
{
for (int i = 2; i <= sqrt(x); i++)
if (x % i == 0)return false;
return true;
}
int main()
{
int N, M;
scanf("%d %d", &N, &M);
int dnum[10001]; //独立性
bool Visit[10001] = { false }; //判断死循环
bool IsHappy[10001] = { false };
bool IsIndividual[10001] = { false }; //特立独行的数
bool IsCircle[10001] = { false }; //死循环数
int Queue[10001]; //每次迭代中所有待处理的数
int index = 0;
int num, tnum, add;
bool check = false; //true为死循环,false为幸福数
for (int i = 0; i < M - N + 1; i++)
{
num = N + i;
check = false;
while (true) { //对num进行迭代
if (num == 1 || IsHappy[num]) { //遇到1或是幸福数
Queue[index++] = num; Visit[num] = true; break;
}
else if (Visit[num] || IsCircle[num]) { Queue[index++] = num; Visit[num] = true; check = true; break; } //遇到死循环数
Queue[index++] = num;
Visit[num] = true;
tnum = 0;
while(num){
add = num % 10;
tnum += add * add;
num/=10;
}
num = tnum;
}
for (int j = 0; j < index; j++) Visit[Queue[j]] = false; //初始化Visit数组
if (IsHappy[Queue[index - 1]]) //处理遇到幸福数的情况
{
if(index==1)continue; //若A就是B,跳过处理
IsIndividual[Queue[index - 1]] = false; //B一定不是特立独行的数
IsIndividual[Queue[0]] = true; //A暂设为特立独行的数
//printf("[[[%d]]]-%d\n", Queue[0],Queue[index-1]);
for (int j = index - 2; j >= 0; j--) //A至B的所有数设为幸福数,并设置独立性
{
dnum[Queue[j]] = dnum[Queue[j + 1]] + 1;
IsHappy[Queue[j]] = true;
}
}
else if (IsCircle[Queue[index - 1]]) //处理遇到死循环数的情况
{
for (int j = index - 2; j >= 0; j--)
{
IsCircle[Queue[j]] = true;
}
}
else
{
if (!check) { //迭代至到1,标记A为特立独行的数
IsIndividual[Queue[0]] = true; //printf("---%d---\n", Queue[0]);
}
for (int j = 0; j < index; j++)
{
if (check)IsCircle[Queue[j]] = true; //处理迭代至遇到死循环的情况
else { //处理迭代至1的情况
IsHappy[Queue[j]] = true;
dnum[Queue[j]] = index - j-1;
}
}
}
index = 0;
}
int ans = 0;
for (int i = 0; i < M-N+1; i++)
if (IsIndividual[N + i]) {
ans += 1; printf("%d %d\n", N + i, IsPrime(N + i) ? dnum[N + i] * 2 : dnum[N + i]);
}
if (ans == 0)printf("SAD");
}