鱼C论坛

 找回密码
 立即注册
查看: 2464|回复: 9

题目74:包含60个不重复项的阶乘链有多少个?

[复制链接]
发表于 2015-11-5 17:01:25 | 显示全部楼层 |阅读模式

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

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

x
Digit factorial chains

The number 145 is well known for the property that the sum of the factorial of its digits is equal to 145:

1! + 4! + 5! = 1 + 24 + 120 = 145

Perhaps less well known is 169, in that it produces the longest chain of numbers that link back to 169; it turns out that there are only three such loops that exist:

169 → 363601 → 1454 → 169
871 → 45361 → 871
872 → 45362 → 872

It is not difficult to prove that EVERY starting number will eventually get stuck in a loop. For example,

69 → 363600 → 1454 → 169 → 363601 (→ 1454)
78 → 45360 → 871 → 45361 (→ 871)
540 → 145 (→ 145)

Starting with 69 produces a chain of five non-repeating terms, but the longest non-repeating chain with a starting number below one million is sixty terms.

How many chains, with a starting number below one million, contain exactly sixty non-repeating terms?

题目:

数字 145 有一个著名的性质:其所有位上数字的阶乘和等于它本身。

1! + 4! + 5! = 1 + 24 + 120 = 145

169 不像 145 那么有名,但是 169 可以产生最长的能够连接回它自己的数字链。事实证明一共有三条这样的链:
169 → 363601 → 1454 → 169
871 → 45361 → 871
872 → 45362 → 872

不难证明每一个数字最终都将陷入一个循环。例如:

69 → 363600 → 1454 → 169 → 363601 (→ 1454)
78 → 45360 → 871 → 45361 (→ 871)
540 → 145 (→ 145)

从 69 开始可以产生一条有 5 个不重复元素的链,但是以一百万以下的数开始,能够产生的最长的不重复链包含 60 个项。

一共有多少条以一百万以下的数开始的链包含 60 个不重复项?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-10-16 15:58:32 | 显示全部楼层
进度:5 %  用时:9.589秒 >>>进度:10 %  用时:19.738秒 >>>进度:15 %  用时:29.751秒 >>>进度:20 %  用时:40.014秒 >>>进度:25 %  用时:50.148秒 >>>进度:30 %  用时:60.717秒 >>>进度:35 %  用时:70.462秒 >>>进度:40 %  用时:80.854秒 >>>进度:45 %  用时:90.833秒 >>>进度:50 %  用时:101.681秒 >>>进度:55 %  用时:111.471秒 >>>进度:60 %  用时:122.204秒 >>>进度:65 %  用时:133.301秒 >>>进度:70 %  用时:144.257秒 >>>进度:75 %  用时:154.717秒 >>>进度:80 %  用时:165.559秒 >>>进度:85 %  用时:176.494秒 >>>进度:90 %  用时:187.150秒 >>>进度:95 %  用时:198.313秒 >>>进度:100 %  用时:209.492秒 >>>答案: 402 总共用时:209.820秒

算法时间蛮长的,应该可以优化的。
  1. from math import factorial as fct
  2. def chain(n):
  3.     chains = [n]
  4.     count, calc = 1, 0
  5.     for i in str(n):
  6.         calc += fct(int(i))
  7.     while calc not in chains:
  8.         chains.append(calc)
  9.         count += 1
  10.         n1 = calc
  11.         calc = 0
  12.         for i in str(n1):
  13.             calc += fct(int(i))
  14.     return count

  15. chainlist = []
  16. for i in range(1,1000001):
  17.     if i % 50000 == 0:
  18.         middle = clock()
  19.         print ('进度:%d' % int(i/10000), '%',' 用时:%.3f秒 >>>' % (middle-start), end ='')
  20.     if chain(i) == 60:
  21.         chainlist.append(i)
  22. end = clock()
  23. print ('答案: %d' % len(chainlist), '总共用时:%.3f秒' % (end-start))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 1

使用道具 举报

发表于 2017-2-5 21:27:19 | 显示全部楼层
新手学习  很多地方很幼稚
答案  402
  1. # -*- coding: utf-8 -*-
  2. import math
  3. import time
  4. start=time.clock()
  5. list2=[]
  6. list3=[]
  7. list4=[]
  8. def fen_2(m):
  9.     list1=[]
  10.     list2.append(m)
  11.     for n in str(m) :
  12.         n=int(n)
  13.         list1.append(math.factorial(n))
  14.     if len(list2)!=len(set(list2)):
  15.         list2.pop()
  16.         return len(list2)
  17.     return  fen_2(sum(list1))
  18. def fen(x):
  19.     global list2
  20.     list2 =[]
  21.     return(fen_2(x))
  22. for i in range(1,1000000):
  23.     if fen(i)>=60:
  24.         list3.append(i)
  25. print(len(list3) )
  26. for i in list3:
  27.     fen(i)
  28.     list4.extend(list(set(list2)&set(list3 )))
  29. print(list4 == list3)
  30. end=time.clock()
  31. print('运行耗时:%f'%(end-start ))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-2-16 15:44:48 | 显示全部楼层
  1. # encoding:utf-8
  2. # 寻找100万以下60项的阶乘链  145 = 1!+2!+3!
  3. from time import time
  4. from math import factorial

  5. def getFac(n):
  6.     result = 0
  7.     while n >= 10:
  8.         result += factorial(n % 10)
  9.         n = n // 10
  10.     return result + factorial(n)

  11. def euler072(N=100):
  12.     d_facs = {}
  13.     s_facs = set()
  14.     count = 0
  15.     for n in range(1, 1000001):
  16.         if str(sorted(str(n))) in s_facs:
  17.             count+=1
  18.         else:
  19.             l_tmp = [n]
  20.             tmp,k = 0,n
  21.             while True:
  22.                 tmp = getFac(k);
  23.                 if tmp not in l_tmp:
  24.                     l_tmp.append(tmp)
  25.                     k = tmp
  26.                 else:
  27.                     break
  28.             if len(l_tmp)>=60:
  29.                 count+=1
  30.                 d_facs[str(sorted(str(n)))] = l_tmp
  31.     print(count)   
  32.    
  33. if __name__ == '__main__':
  34.     start = time()
  35.     euler072()
  36.     print('cost %.6f sec' % (time() - start))
复制代码

402
cost 62.502249 sec
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-10-14 21:35:38 | 显示全部楼层
用了新解法:
程序是matlab
结果是
   402

时间已过 0.771700 秒。
>>
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-3-12 22:42:24 | 显示全部楼层
  1. from time import perf_counter


  2. def factorial(n):
  3.     if n == 0 or n == 1:
  4.         return 1
  5.     else:
  6.         return n * factorial(n-1)

  7. def generate_unrepetition_link(n):
  8.     unrepetition_link = [n]
  9.     num_str = str(n)
  10.     while True:
  11.         sum_ = 0
  12.         for each in num_str:
  13.             sum_ += factorial(int(each))
  14.         if sum_ not in unrepetition_link:
  15.             unrepetition_link.append(sum_)
  16.             num_str = str(sum_)
  17.         else:
  18.             break
  19.     return unrepetition_link
  20. def main():
  21.     n = 0
  22.     for i in range(5, 1000000):
  23.         if len(generate_unrepetition_link(i)) == 60:
  24.             n += 1
  25.     print(n)


  26. if __name__ == '__main__':
  27.     start = perf_counter()
  28.     main()
  29.     end = perf_counter()
  30.     print("time uesd:", end - start)
复制代码


结果:
402
time uesd: 103.1872067770146s
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-8-1 14:37:11 | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-1-7 20:10 编辑

记录下思路,以后再写
0.出现过的不重复计算
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-8-30 10:57:55 | 显示全部楼层
402

Process returned 0 (0x0)   execution time : 0.219 s
Press any key to continue.
动态规划+记忆化搜索
设f(x)为x各位数阶乘之和
设集合

                               
登录/注册后可看大图

设len(x)为以x开始的链的不重复项数,则状态转移方程

                               
登录/注册后可看大图

  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;

  4. const int f[] = {1,1,2,6,24,120,720,5040,40320,362880};

  5. const int len3[] = {169,1454,363601};
  6. const int len2[] = {871,872,45361,45362};
  7. const int len1[] = {0,1,2,145,40585};

  8. const int M = 1e6;
  9. int dp[M*10] = {0};
  10. int mx = 0;

  11. int f_sum(int x){
  12.   int res = 0;
  13.   if (x == 0) return 1;
  14.   while(x){
  15.     res += f[x % 10];
  16.     x /= 10;
  17.   }
  18.   return res;
  19. }

  20. int len(int x){
  21.   //mx = max(mx,x);
  22.   int & ans = dp[x];
  23.   if (ans)  return ans;

  24.   if (find(len3,len3 +3,x) != len3 +3)  return ans = 3;
  25.   if (find(len2,len2 +4,x) != len2 +4)  return ans = 2;
  26.   if (find(len1,len1 +5,x) != len1 +5)  return ans = 1;

  27.   return ans = len(f_sum(x)) + 1;
  28. }

  29. int main(){
  30.   int cnt = 0;
  31.   for (int i = 0;i <= M;i++)
  32.     if (len(i) == 60) ++cnt;

  33.   //cout << mx << endl;
  34.   cout << cnt << endl;
  35.   return 0;
  36. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-12 16:38:52 | 显示全部楼层
  1. /*
  2. 答案:402
  3. 耗时:4.07265秒(单核)
  4.       0.658726秒(六核)
  5. */
  6. #include <iostream>
  7. #include <unordered_set>
  8. #include <omp.h>
  9. using namespace std;

  10. const int f[] = { 1,1,2,6,24,120,720,5040,40320,362880 };

  11. int GetFS(int n)
  12. {
  13.   int nS = 0;
  14.   while (n > 0)
  15.   {
  16.     nS += f[n % 10];
  17.     n /= 10;
  18.   }
  19.   return nS;
  20. }

  21. int main(void)
  22. {
  23.   double t = omp_get_wtime();
  24.   int nCount = 0;
  25.   unordered_set<long long> us;
  26. #pragma omp parallel for private(us) reduction(+:nCount)
  27.   for (int i = 1; i <= 1000000; ++i)
  28.   {
  29.     us.clear();
  30.     int k = i;
  31.     while (true)
  32.     {
  33.       auto itr = us.find(k);
  34.       if (itr != us.end())
  35.         break;
  36.       us.insert(k);
  37.       k = GetFS(k);
  38.     }
  39.     if (us.size() >= 60)
  40.       ++nCount;
  41.   }
  42.   t = omp_get_wtime() - t;
  43.   cout << nCount << endl << t << endl;
  44.   return 0;
  45. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-3-1 10:02:01 | 显示全部楼层
本帖最后由 TLM 于 2023-3-1 10:03 编辑

储存计算过的数值,阶乘也提前算好
402
Time:1.909942865371704s
  1. import time
  2. st=time.time()
  3. n=1000000
  4. # 获取阶乘数列
  5. jiecheng=[1]
  6. for i in range(1,10):
  7.     jiecheng.append(jiecheng[-1]*i)
  8. # 创建dict()
  9. data=dict()
  10. def getl(n):
  11.     if n in data:
  12.         return data[n]
  13.     data2=dict()
  14.     nn=n
  15.     u=0
  16.     while nn not in data2:
  17.         num=0
  18.         ii=nn
  19.         while ii>0:
  20.             num=jiecheng[ii%10]+num
  21.             ii=ii//10
  22.         data2[nn]=len(data2)+1
  23.         nn=num
  24.         if nn in data:
  25.             u=data[nn]-1
  26.             data2[nn]=len(data2)+1
  27.             break
  28.     for j in data2:
  29.         if data2[j]>=data2[nn]:
  30.             data[j]=len(data2)+1-data2[nn]+u
  31.         else:
  32.             data[j]=len(data2)+1-data2[j]+u
  33.     return data[n]
  34. numsum=0
  35. for i in range(69,n+1):
  36.     # print(getl(i))
  37.     if getl(i)>=60:
  38.         numsum=numsum+1
  39. print(numsum)
  40. # print(data)
  41. print('Time:{}s'.format(time.time()-st))
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-2 11:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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