鱼C论坛

 找回密码
 立即注册
查看: 3180|回复: 6

题目95:找出元素都不超过一百万的亲和链中最小的元素

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

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

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

x
Amicable chains

The proper divisors of a number are all the divisors excluding the number itself. For example, the proper divisors of 28 are 1, 2, 4, 7, and 14. As the sum of these divisors is equal to 28, we call it a perfect number.

Interestingly the sum of the proper divisors of 220 is 284 and the sum of the proper divisors of 284 is 220, forming a chain of two numbers. For this reason, 220 and 284 are called an amicable pair.

Perhaps less well known are longer chains. For example, starting with 12496, we form a chain of five numbers:

12496 → 14288 → 15472 → 14536 → 14264 (→ 12496 → ...)


Since this chain returns to its starting point, it is called an amicable chain.

Find the smallest member of the longest amicable chain with no element exceeding one million.


题目:

一个数的真因子是指除了其本身以外的所有因子。例如,28 的真因子是 1,2,4,7 和 14。因为这些因子之和等于 28,我们称 28 为一个完美数。

有趣的是,220 的真因子之和是 284,而 284 的真因子之和是 220,形成了一个两个元素的链。因此 220 和 284 被称为一个亲和对。

可能更长的链就不那么为人所知了,例如,从 12496 开始,我们可以得到一个五个元素的链:

12496 → 14288 → 15472 → 14536 → 14264 (→ 12496 → ...)


因为这条链最后回到了开始的数,它被称为一条亲和链。

对于元素都不超过一百万的亲和链,找出最长的亲和链中最小的元素。

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

使用道具 举报

发表于 2016-11-22 21:17:12 | 显示全部楼层
  1. import math
  2. def Hr(x):
  3.     count =1
  4.     for i in range(2,int(math.sqrt(x)+1)):
  5.         if x % i == 0:
  6.             if i!= x/i:
  7.                 count += i+x/i
  8.             else:
  9.                 count += i
  10.     return int(count)
  11. def Prime(x):
  12.     if x > 1:
  13.         if x==2:
  14.             return True
  15.         if x%2==0:
  16.             return False
  17.         for i in range(3,int(math.sqrt(x)+1),2):
  18.             if x%i==0:
  19.                 return False
  20.         return True
  21.     return False
  22. i=4
  23. temp = i
  24. list1=[]
  25. list2 = []
  26. while True:
  27.     if not Prime(i):
  28.         list2=[]
  29.         while temp != 1:
  30.             temp = Hr(temp)
  31.             if temp in list2:
  32.                 break
  33.             if i not in list2:
  34.                 list2.append(i)
  35.             if temp not in list2:
  36.                 list2.append(temp)
  37.             if temp > 1000000:
  38.                 break
  39.                
  40.             if temp == i:
  41.                 break
  42.         if temp == i and temp<1000000:
  43.             list1.append(list2)
  44.     i += 1
  45.     temp = i
  46.     if i > 1000000:
  47.         break
  48. tmp = 0
  49. for each in list1:
  50.     each.sort()
  51.     if len(each) > tmp:
  52.         tmp = len(each)
  53. list3=[]
  54. for each in list1:
  55.     if len(each) == tmp:
  56.         list3.append(each[0])
  57. list3.sort()
  58. print(list3[0])
复制代码

效率低得不行,结果:14316
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-1-5 17:06:33 | 显示全部楼层
本帖最后由 jerryxjr1220 于 2017-1-5 21:59 编辑
愤怒的大头菇 发表于 2016-11-22 21:17
效率低得不行,结果:14316


我的效率也好低,2分钟才能出结果。。。
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Thu Jan  5 21:21:52 2017

  4. @author: Jerry Xu
  5. """

  6. primes = [True]*1000001
  7. primes[0], primes[1] = False, False
  8. for i,prime in enumerate(primes):
  9.         if prime:
  10.                 for j in range(i*i,1000001,i):
  11.                         primes[j] = False
  12. dic = {}
  13. chain = {}
  14. chains = {}
  15. def ele(n):
  16.         if primes[n]:
  17.                 dic[n] = [1]
  18.         else:
  19.                 dic[n] = [1]
  20.                 for i in range(2,int(n**0.5+1)):
  21.                         if n % i == 0 and i*i != n:
  22.                                 dic[n] += [i,n//i]
  23.                         elif i*i == n:
  24.                                 dic[n] += [i]
  25.         chain[n] = sum(dic[n])
  26. def find(x):
  27.         tmp = [x]
  28.         y = chain[x]
  29.         while True:
  30.                 if y > 1000000:
  31.                         tmp = []
  32.                         chains[y] = 0
  33.                         break
  34.                 else:
  35.                         if y in tmp:
  36.                                 index = tmp.index(y)
  37.                                 if len(tmp)-index > chains.get(y,0):
  38.                                         chains[y] = len(tmp)-index
  39.                                 break
  40.                         else:
  41.                                 tmp.append(y)
  42.                                 y = chain[y]
  43.         return y,chains[y]
  44. for i in range(1,1000001):
  45.         ele(i)
  46. maxlength = 0
  47. for i in range(1,1000001):
  48.         if find(i)[1] > maxlength:
  49.                 maxlength = find(i)[1]
  50.                 maxi = find(i)[0]
  51. k = maxi
  52. longest = []
  53. for i in range(maxlength):
  54.         k = chain[k]
  55.         longest.append(k)
  56. print (min(longest))
复制代码

结果和你是一样的:
14316
[Finished in 123.9s]
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-3-10 14:54:43 | 显示全部楼层
  1. # encoding:utf-8
  2. # 找出不超过100万的亲和链中的最小元素
  3. from time import time
  4. N = 1000000
  5. l_sums, l_lens = [1] * (2 * N), [0] * (2 * N)
  6. def getFacSum():
  7.     for i in range(2, N // 2 + 1):
  8.         for t in range(2 * i, N + 1, i):
  9.             l_sums[t] += i
  10. def euler095():
  11.     getFacSum()
  12.     max_len_nums = set()
  13.     for i in range (1, N + 1):
  14.         s_t , t, flag = list(), i, False
  15.         s_t.append(t)
  16.         while True:
  17.             if l_sums[t] > N + 1:
  18.                 break
  19.             if l_sums[t] not in s_t:
  20.                 s_t.append(l_sums[t])
  21.                 t = l_sums[t]
  22.             else:
  23.                 s_t = s_t[s_t.index(l_sums[t]):]
  24.                 flag = True
  25.                 break
  26.         if flag:
  27.             l_lens[s_t[0]] = len(s_t)
  28.             if len(s_t) > len(max_len_nums):
  29.                 max_len_nums = s_t.copy()
  30.     print(max_len_nums)
  31.     print(min(max_len_nums))
  32. if __name__ == '__main__':
  33.     start = time()
  34.     euler095()
  35.     print('cost %.6f sec' % (time() - start))
复制代码

[14316, 19116, 31704, 47616, 83328, 177792, 295488, 629072, 589786, 294896, 358336, 418904, 366556, 274924, 275444, 243760, 376736, 381028, 285778, 152990, 122410, 97946, 48976, 45946, 22976, 22744, 19916, 17716]
14316
cost 16.423642 sec
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-4 15:10:14 | 显示全部楼层
  1. bound = int(1e6)

  2. count = [0] * bound
  3. for i in range(1, bound // 2):
  4.   for j in range(2 * i, bound, i):
  5.     count[j] += i

  6. flag = [0] * bound
  7. def find(n):
  8.   if flag[n] == 0:
  9.     s = set()
  10.     p = n
  11.     while p not in s:
  12.       s.add(p)
  13.       flag[p] = -1
  14.       p = count[p]
  15.       if p > bound:
  16.         return -1
  17.     l = list()
  18.     while p in s:
  19.       l.append(p)
  20.       s.remove(p)
  21.       p = count[p]
  22.     for i in l:
  23.       flag[i] = len(l)
  24.   return flag[n]

  25. print(max(range(1, bound), key = find))
复制代码


https://github.com/devinizz/project_euler/blob/master/page02/95.py

评分

参与人数 1荣誉 +1 收起 理由
永恒的蓝色梦想 + 1 鱼C有你更精彩^_^

查看全部评分

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

使用道具 举报

发表于 2020-12-31 22:23:55 From FishC Mobile | 显示全部楼层
本帖最后由 永恒的蓝色梦想 于 2021-2-19 10:58 编辑

C++ 151ms
  1. #include<iostream>
  2. #include<vector>
  3. #include<unordered_map>



  4. int main() {
  5.     using namespace std;
  6.     ios::sync_with_stdio(false);

  7.     constexpr static unsigned int UPPER_BOUND = 1000000;
  8.     static unsigned int prime_divisor_sum[UPPER_BOUND + 1];
  9.     unordered_map<unsigned int, unsigned int> indecies;
  10.     vector<unsigned int> chain;
  11.     unsigned int i, copy_i, temp, min_of_longest = 0, max_length = 0;
  12.     unsigned int & index = copy_i, & length = temp;//别名


  13.     for (i = 1; i <= UPPER_BOUND / 2; i++) {
  14.         for (temp = i << 1; temp <= UPPER_BOUND; temp += i) {
  15.             prime_divisor_sum[temp] += i;
  16.         }
  17.     }


  18.     for (i = 1; i <= UPPER_BOUND; i++) {
  19.         if (prime_divisor_sum[i]) {
  20.             chain.push_back(i);
  21.             indecies[i] = 1;
  22.             copy_i = prime_divisor_sum[i];
  23.             prime_divisor_sum[i] = 0;

  24.             for (;;) {
  25.                 if (copy_i > UPPER_BOUND) {
  26.                     break;
  27.                 }
  28.                 else if (prime_divisor_sum[copy_i]) {
  29.                     chain.push_back(copy_i);
  30.                     indecies[copy_i] = chain.size();
  31.                     temp = prime_divisor_sum[copy_i];
  32.                     prime_divisor_sum[copy_i] = 0;
  33.                     copy_i = temp;
  34.                 }
  35.                 else {
  36.                     if (index = indecies[copy_i]) {
  37.                         length = chain.size() - index;//比真的长度少1

  38.                         if (length > max_length) {
  39.                             max_length = length;

  40.                             for (min_of_longest = chain[index - 1]; index < chain.size(); index++) {
  41.                                 if (chain[index] < min_of_longest) {
  42.                                     min_of_longest = chain[index];
  43.                                 }
  44.                             }
  45.                         }
  46.                     }

  47.                     break;
  48.                 }
  49.             }

  50.             indecies.clear();
  51.             chain.clear();
  52.         }
  53.     }


  54.     cout << min_of_longest << endl;
  55.     return 0;
  56. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-1-27 17:22:36 | 显示全部楼层
  1. /*
  2. 答案:14316
  3. 耗时:2.58101秒(单核)
  4.       0.287085秒(八核)
  5. */
  6. #include <iostream>
  7. #include <algorithm>
  8. #include <vector>
  9. #include <cmath>
  10. #include <omp.h>
  11. using namespace std;

  12. const int N = 1000000;
  13. int a[N + 1];

  14. int getAmi(int n)
  15. {
  16.   int r = 1;
  17.   for (int i = 2; i <= (int)sqrt((double)n); ++i)
  18.   {
  19.     if (n%i == 0)
  20.     {
  21.       int m = n / i;
  22.       if (m != i)
  23.         r += m + i;
  24.       else
  25.         r += i;
  26.     }
  27.   }
  28.   if (r <= N)
  29.     return r;
  30.   else
  31.     return -1;
  32. }

  33. int main(void)
  34. {
  35.   double t = omp_get_wtime();
  36.   int ps = omp_get_num_procs();
  37.   int *nMaxLens = new int[ps], *nMinElements = new int[ps];
  38. #pragma omp parallel shared(nMaxLens,nMinElements)
  39.   {
  40. #pragma omp for
  41.     for (int i = 0; i < ps; ++i)
  42.     {
  43.       nMaxLens[i] = 0;
  44.       nMinElements[i] = N;
  45.     }
  46. #pragma omp for schedule(guided,4)
  47.     for (int i = 2; i <= N; ++i)
  48.       a[i] = getAmi(i);
  49. #pragma omp for schedule(dynamic)
  50.     for (int i = 2; i <= N; ++i)
  51.     {
  52.       int pt = omp_get_thread_num();
  53.       vector<int> v;
  54.       int k = i;
  55.       bool bFind = false;
  56.       while (true)
  57.       {
  58.         v.push_back(k);
  59.         k = a[k];
  60.         if (k <= 1)
  61.           break;
  62.         auto itr = find(v.begin(), v.end(), k);
  63.         if (itr != v.end())
  64.         {
  65.           int nc = int(v.end() - itr);
  66.           if (nc > nMaxLens[pt])
  67.           {
  68.             nMaxLens[pt] = nc;
  69.             nMinElements[pt] = *min_element(itr, v.end());
  70.           }
  71.           break;
  72.         }
  73.       }
  74.     }
  75.   }
  76.   for (int i = 1; i < ps; ++i)
  77.   {
  78.     if (nMaxLens[i] > nMaxLens[0])
  79.     {
  80.       nMaxLens[0] = nMaxLens[i];
  81.       nMinElements[0] = nMinElements[i];
  82.     }
  83.   }
  84.   t = omp_get_wtime() - t;
  85.   cout << nMinElements[0] << endl << t << endl;;
  86.   delete[] nMaxLens;
  87.   delete[] nMinElements;
  88.   return 0;
  89. }
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-5-11 15:21

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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