题目描述 :
在这里首先了解一个小知识 , 当快乐数始终变不了1 , 陷入无限循环时 , 最终得到的结果就会是4 , 所以只需要判断结果是否等于4 , 如果为4 , 则就不是快乐数
代码如下 :
int Num(int x)
{
int ret=0;
while(x){
ret+=(x%10)*(x%10);
x/=10;
}
return ret;
}
bool isHappy(int n) {
if(n<=0)
return false;
while(n!=1){
n=Num(n);
if(n==4)
return false;
}
return true;
}
快乐数字由以下过程定义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是快乐数。
例如7是快乐数,因为7->49->97->130->10->1。(77=49,44+99=97,99+7*7=130…如此类推)
显然1是第一个快乐数。
有Q个询问,每个询问给出一个数k,你需要输出第k个快乐数。
Input
第一行一个Q,代表询问的个数(Q<=100000)
接下来Q行,每行一个数字k(k<150000)
Output
每行输出一个数,代表第k个数
Sample Input
2 1 2
Sample Output
1 7
ps:开始死循环没找不是快乐数在哪里断开。后来发现许多不是快乐数最后都会到4.
2->4->16->37->58->89->145->42->20->4
5->25->29->85->89->…->4
6->36->45->41->17->50->25->…->4
#include<iostream>
using namespace std;
const int maxn = 1000000;
const int maxm = 150000;
bool vis[maxn]={0};
int num[maxm+10];
int g(int n){
if (n!=1 && n!=7 && n<10)//易知10以内的数就1和7,该条件为递归结束出口
return 0;
int sum = 0;
while (n){
int t = n % 10;
n /= 10;
sum += t * t;
}
if (vis[sum]) return 1;
else return g(sum);
}
void init (){
vis[1] = 1;
num[1] = 1;
for (int i=2,j=2;j<=maxm;i++){
if (g(i)){
vis[i] = 1;
num[j++] = i;
}
}
}
int main(){
init();
int t;
scanf("%d",&t);
while (t--){
int n;
scanf("%d",&n);
printf("%d\n",num[n]);
}
//for (int i=1;i<=20;i++)
// printf("%d ",num[i]);
return 0;
}
以上是个打表的过程,通过记忆化搜索已经用空间换取了大部分时间,还可以结合许多非快乐数不等于4这个条件来改善代码。