HDU6463 超级无敌简单题 [暴力or小技巧]

Problem Description

通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
通常来说,题面短的题目一般都比较难,所以我要把题面写得很长很长。
鸽子数字由以下过程定义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是鸽子数。
例如7是鸽子数,因为7->49->97->130->10->1。(7*7=49,4*4+9*9=97,9*9+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

题意:就是寻找循环平方和最后能为1的数字,题目中叫鸽子数,实际上叫快乐数(happy number)有以下的特性:在给定的进位制下,该数字所有数位(digits)的平方和,得到的新数再次求所有数位的平方和,如此重复进行,最终结果必为1,现在让你求出第K个鸽子数。

题解:有两种解法:

1.因为假设一个数有十位,最大即9999999999,他的每一位平方和也才9*9*10即810,所以只需要先判断出1-810中有哪些数字为鸽子数,然后对后面的数进行第一次操作一定在810以内,直接判断是否为鸽子数即可,若第一次操作后为鸽子数,则这个大的数字一定也为鸽子数。

2.暴力打表,将前150000个鸽子数全部打出来,然后需要第几个输出第几个即可。

判断时可以用的规律,如出现{37,58,89,145,42,20,4,16}这几个数字,则一定不是鸽子数,相反也一定不是,比如73。或直接判断是否有4出现,有4出现一定不为鸽子数。

//第一种解法
#include
using namespace std;
#define ll long long
int mark[1005];
int test(int k) {
    int cnt = 0;
    while (k != 1 && cnt < 1000) {
        int tmp = 0;
        while (k != 0) {
            tmp += (k % 10) * (k % 10);
            k /= 10;
        }
        k = tmp;
        cnt++;
    }
    return k==1;
}
int num[150005];
int main() {
    int n,ans,k = 0,temp = 0,p = 0;
    for(int i = 0; i < 1000; i++) {
        if(test(i)) {
            mark[i] = 1;
        }
    }
    int a;
    for(int i = 1,j= 0; i < 150000; j++) {
        a = j;
        int tmp = 0;
        while (a != 0) {
            tmp += (a % 10) * (a % 10);
            a /= 10;
        }
        if(mark[tmp]==1){
            num[i] = j;
            i++;
//            printf("!!%d\n",j);
        }
    }
    scanf("%d",&n);
    for(int i = 0; i < n; i++) {
        scanf("%d",&k);
        printf("%d\n",num[k]);
    }
}

大佬写的暴力:https://blog.csdn.net/weixin_43272781/article/details/88601829

你可能感兴趣的:(训练赛)