(原创)广东工业大学第十四届程序设计竞赛 鸽子数

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)这道题得先理解一下鸽子数的含义:从任何正整数开始,将数字替换为其各个数位的平方和,并重复该过程,直到该数字等于1。如果不能,则这个数字不是鸽子数。
(2)题目是将自然数从小到大排序,输出第k个鸽子数;
这道题可以先预处理,先将150000内的鸽子数先处理出来,才不用每次查询每次再循环一遍鸽子数,肯定会超时
注意:先将150000内的鸽子数先处理出来,这里特别要注意,不能从i = 1到 i = 150000 找鸽子数,因为该范围的鸽子数肯定小于150000(并不是所有的数都是鸽子数),所以应范围稍微大于150000;
代码如下:
 1 #include<iostream>
 2 using namespace std;
 3 
 4 
 5 int get(int tmp)          //将每个正整数分解成各位数的平方和;
 6  {
 7          int ans = 0;
 8         while (tmp>0)
 9      {
10             ans += (tmp% 10) * (tmp% 10);
11             tmp  = tmp/ 10;
12      }
13 
14   
15         return ans;
16  }
17  bool gezi(int n) 
18 {     
19      int temp = n;
20       while (1) 
21    {
22           temp = get(temp);     //获得分解后的数,比如get(49)获得97(4²+9²);
23          if (temp == 2 ||temp == 3 ||temp == 4 ||temp == 5||temp == 6 || temp == 16 || temp == 20|| temp == 37 || temp == 42 || temp == 58 ||temp == 89 || temp == 145  )
24    {  //这个优化源于我一开始题目读错,以为是输入该数,判断是否为鸽子数,题目有2,结果2的分解是一个死循环,将2分解过程中的一个循环中的数都不会符合条件;再加上3,4,5,6,均不是鸽子数,因为题目说7是第二个鸽子数;
25                 return false;
26     } else
27          if (temp == 1) 
28         {
29                 return true;
30         }
31     }
32 }
33 
34 
35 long long int count1 = 1;
36 long long int flag[1500005];
37 int q ,n;
38 int main()
39 {
40     cin>>q;
41     for( long long int i = 1 ;i <= 1050000;i++)   //这里不能只是到150000  因为这样的话找不到鸽子数范围到150000,范围得开再大点;
42     {
43         if(gezi(i))
44         {
45             flag[count1] = i;     //将鸽子数记录下来,并记录其序号,方便后面直接输出;
46             count1++;
47         }
48     }
49     for( int i = 0 ; i < q;i++)
50     {
51         cin>>n;
52         cout<<flag[n]<<endl;    //直接根据序号输出鸽子数;
53     }
54     return 0;
55 }
56 
57 
58  
 
 
原文地址:https://www.cnblogs.com/yewanting/p/10543792.html