鱼C论坛

 找回密码
 立即注册
查看: 2916|回复: 11

题目92:考察具有有趣性质的平方数链

[复制链接]
发表于 2016-8-11 23:14:50 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 永恒的蓝色梦想 于 2020-6-5 14:24 编辑
Square digit chains

A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.

For example,

44 → 32 → 13 → 10 → 1 1
85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that EVERY starting number will eventually arrive at 1 or 89.

How many starting numbers below ten million will arrive at 89?


题目:

通过将一个数各位的平方不断相加,直到遇到已经出现过的数字,可以形成一个数字链。

例如:
44 → 32 → 13 → 10 → 11
85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89

因此任何到达 1 或 89 的数字链都会陷入无限循环。令人惊奇的是,以任何数字开始,最终都会到达 1 或 89。

以一千万以下的数字 n 开始,有多少个 n 会到达 89?
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2016-8-31 16:48:19 | 显示全部楼层
结果12587445
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace  std;
  5. /*
  6. 返回一个数字各位数平方相加后的数
  7. */
  8. int get(int num)
  9. {
  10.         int sum=0;
  11.         int t = num;
  12.         while(num)
  13.         {
  14.                 sum+= (num%10)*(num%10);
  15.                 num/=10;
  16.         }
  17.         return sum;
  18. }
  19. int main()
  20. {
  21.         //限制从1KW
  22.         vector<int> result;
  23.         int j = 0;
  24.         int sum=0;//统计有89的数字
  25.         for (int i =1;i<=10000000;i++)
  26.         {
  27.                 j=i;
  28.                 int value = 0;
  29.                
  30.        
  31.                         //获取这个数字各位数平方和
  32.                         while(1)
  33.                         {

  34.                        
  35.                                 value = get(j);
  36.                                 if(value==89) sum++;
  37.                                 if(result.end()==find(result.begin(),result.end(),value))
  38.                                 {
  39.                                         //没找到到了
  40.                                         result.push_back(value);
  41.                                         j=value;
  42.                                        
  43.                                 }else
  44.                                 {
  45.                                         //找到 退出
  46.                                         result.push_back(value);
  47.                                         break;
  48.                                           
  49.                                 }

  50.                         }
  51.                         //输出结果
  52.                        
  53.                         //std::cout<<i<<":";
  54.                         for (int m=0;m<result.size();m++)
  55.                         {
  56.                                 //std::cout<<result[m]<<" ";
  57.                         }
  58.                         //std::cout<<endl;
  59.                         result.clear();
  60.        
  61.         }
  62.         std::cout<<"结果"<<sum<<endl;
  63.         return 0;
  64. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-9-18 23:31:59 | 显示全部楼层
10000000以下平方和最大的数是9999999,其平方和为81*7=567。所以,可以先建立一个600以下的字典,其他数在运行过程中一旦碰到字典中的数,马上将1或89作为结果反馈。这样,可以加速运算过程。代码如下,结果为8581146。
  1. def get_sum(x):
  2.     number_list = []
  3.     while x:
  4.         x,temp = divmod(x,10)
  5.         number_list.insert(0,temp)
  6.     return sum([t*t for t in number_list])

  7. num_dict = {}

  8. for i in range(1,600):
  9.     s = i
  10.     while s != 1 and s != 89:
  11.         if num_dict.get(s,0):
  12.             s = num_dict[s]
  13.             break
  14.         s = get_sum(s)
  15.     num_dict[i] = s

  16. count_89 = 0
  17. for i in range(1,10000001):
  18.     s = get_sum(i)
  19.     if num_dict[s] == 89:
  20.         count_89+=1
  21.         
  22. print(count_89)
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-10-18 11:51:14 | 显示全部楼层
QingXin 发表于 2016-9-18 23:31
10000000以下平方和最大的数是9999999,其平方和为81*7=567。所以,可以先建立一个600以下的字典,其他数在 ...

8581146
[Finished in 65.9s]
楼上的方法比我好,我只是暴力求解,花了1分多钟。
  1. def chain(n):
  2.         i = n
  3.         while True:
  4.                 s = 0
  5.                 while True:
  6.                         s += (i%10)**2
  7.                         i = int(i/10)
  8.                         if i == 0:
  9.                                 break
  10.                 i = s
  11.                 if i == 89:
  12.                         return True
  13.                 elif i == 1:
  14.                         return False
  15.                 else:
  16.                         pass

  17. count = 0
  18. for i in range(2,10000000):
  19.         if chain(i):
  20.                 count += 1
  21. print count
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-11-23 10:17:51 | 显示全部楼层
  1. def Loop(x,count=0):
  2.     while x!=1 and x!=89:
  3.         for each in str(x):
  4.             count += int(each)**2
  5.         x = count
  6.         count = 0
  7.     if x ==89:
  8.         return True
  9.     if x == 1:
  10.         return False
  11. total = 0
  12. for i in range(1,10000000):
  13.     if Loop(i,count=0):
  14.         total += 1
  15. print(total)
复制代码

结果:8581146
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-6 16:53:04 | 显示全部楼层
  1. # encoding:utf-8
  2. # 具有有趣性质的平方数链
  3. from time import time
  4. N = 10000000
  5. flag = [0] * (N + 1)
  6. def getNums(n):
  7.     while (n != 1 and n != 89):
  8.         if flag[n] == 1:
  9.             return 1
  10.         elif flag[n] == 89:
  11.             return 89
  12.         sums = 0
  13.         for x in str(n):
  14.             sums += (int(x)) ** 2
  15.         n = sums
  16.     return n

  17. def euler092(N):
  18.     for n in range(1, N):
  19.         t = getNums(n)
  20.         # print(n,t)
  21.         if t == 1:
  22.             flag[n] = 1
  23.         else:
  24.             flag[n] = 89
  25.     print(len([k for (k, v) in enumerate(flag) if v == 89]))      

  26. if __name__ == '__main__':
  27.     start = time()
  28.     euler092(N)
  29.     print('cost %.6f sec' % (time() - start))
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-7-22 11:07:04 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-2-12 20:49 编辑

借鉴3L思路
C++ 265ms
  1. #include<iostream>



  2. constexpr unsigned char arrive_at(unsigned int x)noexcept {
  3.     constexpr unsigned char squares[] = { 0, 1, 4, 9, 16, 25, 36, 49, 64, 81 };
  4.     static unsigned char cache[7 * squares[9] + 1] = {[1] = 1, [89] = 89};
  5.     unsigned int temp;
  6.     unsigned short res = 0;

  7.     while (x) {
  8.         temp = x;
  9.         x /= 10;
  10.         res += squares[temp - x * 10];
  11.     }

  12.     if (cache[res]) {
  13.         return cache[res];
  14.     }

  15.     return cache[res] = arrive_at(res);
  16. }



  17. int main() {
  18.     using namespace std;
  19.     ios::sync_with_stdio(false);

  20.     unsigned int count = 0, num;


  21.     for (num = 1; num < 10000000; num++) {
  22.         count += arrive_at(num) == 89;
  23.     }


  24.     cout << count << endl;
  25.     return 0;
  26. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-19 15:41:00 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2020-6-25 19:57 编辑
QingXin 发表于 2016-9-18 23:31
10000000以下平方和最大的数是9999999,其平方和为81*7=567。所以,可以先建立一个600以下的字典,其他数在 ...


把 get_sum 函数改为
  1. def get_sum(x):
  2.     result = 0
  3.    
  4.     while x:
  5.         x,temp = divmod(x,10)
  6.         result += temp * temp
  7.    
  8.     return result
复制代码
会更好。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-25 13:00:04 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-6-19 15:41
把 get_sum 函数改为会更好。

嗯嗯,谢谢指正!确实,建一个列表占用了时间,这个列表没必要建立的。  版主的代码里面 应该写  result += temp**2 ?太匆忙忘记了吧
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-25 19:57:22 | 显示全部楼层
QingXin 发表于 2020-6-25 13:00
嗯嗯,谢谢指正!确实,建一个列表占用了时间,这个列表没必要建立的。  版主的代码里面 应该写  result  ...

确实是写错了
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-21 10:15:21 | 显示全部楼层
8581146

Process returned 0 (0x0)   execution time : 0.514 s
Press any key to continue.
递归+记忆化搜索
  1. #include<iostream>
  2. using namespace std;

  3. const int M = 1e7;
  4. int e[M] = {0};

  5. int square_sum(int x){
  6.   int res = 0;
  7.   int x0 = x;
  8.   if (e[x0])  return e[x0];

  9.   while(x){
  10.     int t = x % 10;
  11.     res += t*t;
  12.     x /= 10;
  13.   }

  14.   if (res == 1 || res == 89) return e[x0] = res;
  15.   return e[x0] = square_sum(res);
  16. }

  17. int main(){
  18.   int cnt = 0;

  19.   for (int i = 1;i < M;i++){
  20.     square_sum(i);
  21.     if (e[i] == 89) cnt++;
  22.   }
  23.   cout << cnt << endl;
  24.   return 0;
  25. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-17 13:56:20 | 显示全部楼层
  1. /*
  2. 答案:8581146
  3. 耗时:0.314319秒(八核)
  4. */
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <omp.h>
  8. using namespace std;

  9. int v1[5] = { 1,10,13,32,44 };
  10. int v89[9] = { 4,16,20,37,42,58,85,89,145 };
  11. int S[10] = { 0,1,4,9,16,25,36,49,64,81 };

  12. int main(void)
  13. {
  14.   double t = omp_get_wtime();
  15.   int nCount = 0;
  16. #pragma omp parallel for shared(v1,v89,S) reduction(+:nCount)
  17.   for (int n = 1; n <= 10000000; ++n)
  18.   {
  19.     int k = n;
  20.     bool bFind = false;
  21.     while (true)
  22.     {
  23.       int nSum = 0;
  24.       while (k != 0)
  25.       {
  26.         nSum += S[k % 10];
  27.         k /= 10;
  28.       }
  29.       if (binary_search(v1, v1 + 5, nSum))
  30.         break;
  31.       if (binary_search(v89, v89 + 9, nSum))
  32.       {
  33.         bFind = true;
  34.         break;
  35.       }
  36.       k = nSum;
  37.     }
  38.     if (bFind)
  39.       ++nCount;
  40.   }
  41.   t = omp_get_wtime() - t;
  42.   cout << nCount << endl << t << endl;
  43.   return 0;
  44. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-5-11 18:46

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表