鱼C论坛

 找回密码
 立即注册
查看: 4942|回复: 25

[技术交流] 小练习:20160620 算出所有不能写成两个过剩数之和的正整数之和

[复制链接]
发表于 2016-6-19 20:54:15 | 显示全部楼层 |阅读模式

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

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

x
本帖最后由 冬雪雪冬 于 2016-6-27 10:14 编辑

从现在开始我们要开展一批欧拉计划的习题练习。
其实在我们论坛中已有欧拉计划的板块,可能有些鱼油还没注意到。
什么是欧拉计划:http://bbs.fishc.com/thread-60405-1-1.html
我们欧拉板块现已给出了81道题,这批练习将从欧拉计划中选题。其实用python语言完成有很多的优势,可以更简洁更方便的实现。
如果大家有兴趣也可浏览欧拉的英文网站:https://projecteuler.net/archives
这里已经有了500余题,并且你每做对一题,就可以下载到参考答案的pdf文件,看看你的实现方法与参考答案有什么不同,以利于迅速提高自己的水平。


                               
登录/注册后可看大图

好了言归正传,我们开始做小练习。




题目要求:
以python语言完成,如果是python2请注明。
程序以代码文字格式发帖。
题目比较简单,注重程序效率和创意。
答题在一周内完成,即6.27 10:00之前,其后将公开大家的答案,并评比成绩。

另程序和答案可以在网上搜到,希望大家独立完成。


题目:

如果一个数的所有真因子之和等于这个数,那么这个数被称为完全数。例如,28 的所有真因子之和为 1 + 2 + 4 + 7 + 14 = 28,所以 28 是一个完全数。

如果一个数的所有真因子之和小于这个数,称其为不足数,如果大于这个数,称其为过剩数。

12 是最小的过剩数,1 + 2 + 3 + 4 + 6 = 16。因此最小的能够写成两个过剩数之和的数字是 24。经过分析,可以证明所有大于 28123 的数字都可以被写成两个过剩数之和。但是这个上界并不能被进一步缩小,即使我们知道最大的不能表示为两个过剩数之和的数字要比这个上界小。

找出所有不能表示为两个过剩数之和的正整数之和


奖励:
对所有完成程序并得出正确答案的将给予加分奖励,优秀的将额外加分。
在完成一批题目后,将根据每期的完成情况总评评出最佳,会有神秘大奖。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-6-20 00:04:37 | 显示全部楼层
这个是新的题目吗,上期好像暧昧公布呢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-20 08:26:57 | 显示全部楼层
  1. def getdivisor(n):
  2.     from math import sqrt
  3.     result = 1
  4.     for i in range(2, int(sqrt(n)+1)):
  5.         if n%i == 0: result = result + i +n/i
  6.     if n%sqrt(n) == 0 : result -= sqrt(n)
  7.     return result

  8. def getabundant(n):
  9.     result = [12]
  10.     for i in range(13, n):
  11.         if getdivisor(i)>i:
  12.             result.append(i)
  13.     return result

  14. if  __name__ == '__main__':
  15.     abundant = getabundant(28112)
  16.     result = list(range(1, 28125))
  17.     k = 0
  18.     a = 2*abundant[k]
  19.     while (a <= 28124):
  20.         for i in range(k, len(abundant)):
  21.             if (abundant[k]+abundant[i])<=28124 :
  22.                 result[abundant[k]+abundant[i]-1] = 0
  23.             else:               
  24.                 break
  25.         k += 1
  26.         a = 2*abundant[k]
  27.     result = set(result)
  28.     print(sum(result))
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-20 11:22:49 | 显示全部楼层
严重支持
  1. def guosheng(x):
  2.     s = 0
  3.     for i in range(1, int(x**0.5)+1):
  4.         if x % i == 0:
  5.             s += i
  6.             a = x / i
  7.             if a != i:
  8.                 s += a
  9.     if (s - x) > x:
  10.         return True
  11.     else:
  12.         return False

  13. dic = [None]
  14. for i in range(1, 28123):
  15.     dic.append(guosheng(i))

  16. def check(x):
  17.     for i in range(1, int(x/2)+1):
  18.         if dic[i]:
  19.             if dic[x-i]:
  20.                 return True
  21.     return False

  22. s = 0
  23. for num in range(1, 28124):
  24.     if not check(num):
  25.         s += num

  26. print(s)
复制代码

运行结果
  1. >>>
  2. 4179871
  3. >>>
复制代码

评分

参与人数 1荣誉 +7 鱼币 +7 收起 理由
冬雪雪冬 + 7 + 7 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-20 12:44:37 | 显示全部楼层
  1. #欧拉23
  2. import time
  3. times=time.time()
  4. def gsc_all(n):
  5.     result = set()
  6.     for single in range(12,n+1):
  7.         singles = {1}
  8.         for i in range(2,int(single**.5)+1):
  9.             if not single % i:
  10.                 singles.update({i, single // i})
  11.         if sum(singles) > single :
  12.             result.update({single})
  13.         singles = singles & {1}
  14.     result_temp =set()
  15.     result=sorted(result)    #这个集合排序找了很久,百度都是list.sort排序

  16. #这里时间最多,已经找不到优化了
  17.     for i in result:
  18.         for y in result:
  19.             z=i+y
  20.             if z<n+1:
  21.                 if z not in result_temp:
  22.                     result_temp.update({i+y})
  23.             else:
  24.                 break
  25.     return (n*(n+1)/2 -sum(result_temp))

  26. print(gsc_all(28123))
  27. print(time.time()-times)
复制代码

人太少了,我昨天回帖到现在才2个人回帖

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-20 15:50:58 | 显示全部楼层
  1. #-*- coding: UTF-8 -*-
  2. import time
  3. start = time.clock()

  4. def aa(num):#借助bhsx同学的真因子和的算法
  5.     count = num
  6.     dict = {}
  7.     get = dict.get
  8.     for i in range(2, count // 2 + 1):
  9.         for j in range(i, count // i - 1):
  10.             sum = i * j
  11.             dict[sum] = get(sum, 1) + i + (j if j != i else 0)
  12.     return dict

  13. input_num=28123
  14. list_1=[]#初始化过剩数列表
  15. dict_1={}#初始化二个过剩数之和为key的字典
  16. for k,v in aa(input_num).items():#判断过剩数并存入列表list_1
  17.         if k<v:
  18.             list_1.append(k)

  19. for i in range(0,len(list_1)):#二个过剩数求和
  20.         for j in range(0,i+1):
  21.                 z=list_1[i]+list_1[j]
  22.                 if z<=input_num:#过剩数和小于input_num,则将和作为key存入dict_1
  23.                     dict_1[z]=1
  24.                 else:#过剩数和大于等于input_num则跳出
  25.                     break

  26. print(input_num*(input_num+1)/2-sum(dict_1.keys()))

  27. end = time.clock()
  28. print ("read: %f s" % (end - start))
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-20 16:45:48 | 显示全部楼层
本帖最后由 holdme 于 2016-6-22 15:23 编辑
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Thu Jun 16 15:58:04 2016

  4. @author: Yohino_Lab_D4
  5. """
  6. from math import sqrt, floor
  7. from itertools import combinations_with_replacement
  8. import time

  9. start = time.clock()
  10. def divisors_sum(n):
  11.     """求n所有真因子的和"""
  12.     if(n == 1):
  13.         return (0)

  14.     divs = set([1])
  15.     r = floor(sqrt(n))
  16.     if(r**2 == n):
  17.         divs.add(r)

  18.     f = 2
  19.     step = 1
  20.     if(n & 1 == 1):
  21.         f = 3
  22.         step = 2

  23.     while(f <= r):
  24.         if(n % f == 0):
  25.             divs.add(int(n/f))
  26.             divs.add(int(f))
  27.         f = f + step
  28.     return sum(divs)

  29. def judge_abund(n):
  30.     '''判断n是否为过剩数'''
  31.     if divisors_sum(n) > n:
  32.         return True
  33.     else:
  34.         return False

  35. def nonabun_sums(limit = 28123):
  36.     abund_list = [i for i in range(limit) if judge_abund(i)]
  37.     abund_sum_list = set(x+y for x,y in combinations_with_replacement(abund_list,2))
  38.     return sum(i for i in range(limit) if i not in abund_sum_list)

  39. print('所有不能表示为两个过剩数之和的正整数之和为:%s'%str(nonabun_sums()))
  40. print('用时%s秒'%str(time.clock()-start))
复制代码


结果:
  1. 所有不能表示为两个过剩数之和的正整数之和为:4178876
  2. 用时3.2573017684944183秒
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-20 17:31:36 | 显示全部楼层
本帖最后由 Spicebush 于 2016-6-24 15:07 编辑
  1. #答案为4179871
  2. import math
  3. def d(n):
  4.     if n>1:
  5.         factor={1}
  6.         half=math.sqrt(n)
  7.         for i in range(2,int(math.sqrt(n))+1):
  8.             if n%i==0:
  9.                 factor.add(i)
  10.                 factor.add(n//i)
  11.         return sum(factor)
  12.     else:
  13.         return 0
  14. #以上摘自小火木之前在欧拉计划中编的程序,学习了,谢谢!

  15. l_gs = [x for x in range(12, 28112) if d(x)>x]
  16. fw = range(len(l_gs))
  17. l = {0}
  18. n = 0
  19. SUM = sum(range(1,28124))
  20. for j in fw:
  21.     if l_gs[j] > 14061:
  22.         break
  23.     else:
  24.         for k in fw[n:]:
  25.             s = l_gs[j] + l_gs[k]
  26.             if s > 28123:
  27.                 break
  28.             else:
  29.                 if s not in l:
  30.                     SUM -= s
  31.                     l.add(s)
  32.         n += 1
  33. print(SUM)
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-21 08:29:21 | 显示全部楼层
python2.7
  1. import math

  2. def dec(num):
  3.     sum = 1
  4.     for i in range(2,int(math.sqrt(num))+1):
  5.         if num%i == 0:
  6.             sum += i
  7.             if num/i != i:
  8.                 sum += num/i
  9.     if sum > num:
  10.         return num

  11. alist = []
  12. flag = 0
  13. asum = 0
  14. blist = []
  15. for i in range(11,28123):
  16.     if dec(i):
  17.         alist.append(i)
  18. for bnum in alist[::-1]:
  19.     for cnum in alist:
  20.         if bnum > cnum:
  21.             dnum = bnum - cnum
  22.             if dnum in alist:
  23.                 blist.append(bnum)
  24.                 break
  25.         else :
  26.             break
  27. for i in range(1,28123):
  28.     if i not in blist:
  29.         asum += i

  30. print asum
复制代码

答案是297576966
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-21 17:08:19 | 显示全部楼层
本帖最后由 mather 于 2016-6-21 17:09 编辑
  1. over_nums = []
  2. cano_nums = []
  3. for n in range(1,28124):
  4.     is_break = False
  5.     for i in over_nums:
  6.         if n-i not in over_nums:
  7.             continue
  8.         else:
  9.             is_break = True
  10.             break
  11.     if not is_break:
  12.         cano_nums.append(n)
  13.     factor = [1]
  14.     nums = n
  15.     upper = n
  16.     for i in range(2,nums+1):
  17.         if i < upper:
  18.             if nums%i == 0:
  19.                 if i != nums/i:
  20.                     factor = factor + [i,int(nums/i)]
  21.                 else:
  22.                     factor.append(i)
  23.                 upper = i if i>=nums/i else nums/i
  24.         else:
  25.             break
  26.     if sum(factor)>n:
  27.         over_nums.append(n)
  28. print(sum(cano_nums))
复制代码

计算时间有点长~~!后面再看能不能优化~
结果:4179871

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-21 23:15:10 | 显示全部楼层
  1. import math
  2. def d(n):
  3.     if n>1:
  4.         factor={1}
  5.         half=math.sqrt(n)
  6.         for i in range(2,int(math.sqrt (n))+1):
  7.             if n%i==0:
  8.                 factor.add(i)
  9.                 factor.add(n//i)
  10.         return sum(factor)
  11.     else:
  12.         return 0

  13. data=[n for n in range(2,28123) if d(n)>n]
  14. temp=[i for i in range(1,28123)]
  15. for i in data:
  16.     for j in data[data.index(i): ]:
  17.         try:
  18.              temp[i+j-1]=0
  19.         except:
  20.             break

  21. print('不能表示为过剩数之和的正整数之和为:%d'%sum(temp))
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-22 13:45:54 | 显示全部楼层
适用于Python2:
  1. def is_abundant_number(number):
  2.     factor_list = [i for i in range(1, int(number ** 0.5) + 1) if not number % i]
  3.     factor_list.extend([number / i for i in factor_list if i < number ** 0.5])
  4.     return True if sum(factor_list) > 2 * number else False

  5. if __name__ == '__main__':
  6.     m = 20161
  7.     abundant_number_list = [i for i in range(12, m + 1) if is_abundant_number(i)]
  8.     set1 = set(range(1, m + 1))
  9.     set2 = set()
  10.     length = len(abundant_number_list)
  11.     for x in range(length):
  12.         if abundant_number_list[x] > m / 2:
  13.             break
  14.         for y in range(x, length):
  15.             s = abundant_number_list[x] + abundant_number_list[y]
  16.             if s > m:
  17.                 break
  18.             set2.add(s)
  19.     print sum(set1 - set2)
复制代码
运行结果与时间:
QQ拼音截图未命名.png

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-22 20:28:30 | 显示全部楼层
  1. import time
  2. start= time.clock()

  3. def isAbundant(num):
  4.         sum = 0
  5.         for i in range(1,num//2+1):
  6.                 if(num % i ==0):
  7.                         sum += i
  8.         if(sum > num):
  9.                 return True
  10.         return False
  11. sum = 0
  12. arr = []
  13. sumArr = []
  14. for i in range(1,28123):
  15.         if(isAbundant(i)):
  16.                 arr.append(i)
  17. for i in range(len(arr)) :
  18.         for j in range(i,len(arr)) :
  19.                 if (arr[i]+arr[j]) < 28123 :
  20.                         sumArr.append(arr[i] + arr[j])
  21. sumArr = set(sumArr)
  22. for i in range(1,28123):
  23.         if(i not in sumArr):
  24.                 sum += i
  25. print(sum)

  26. end = time.clock()
  27. print ("time: %f s" % (end - start))
复制代码


答案:4179871

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-23 13:20:34 | 显示全部楼层
  1. #定义一个求真因子之和的函数
  2. def proper(num):
  3.     sum = 1
  4.     for x in range(2,num//2+1):
  5.         if num % x == 0:
  6.             sum += x
  7.     return sum

  8. #定义一个函数,当它为两个过剩数之和时返回False ,否则返回Ture
  9. def decide(num):
  10.     for each in abun_set:
  11.         if num > each and ((num-each) in abun_set):
  12.             return True
  13.         elif num < each:
  14.             return False

  15. abun_set ={x for x in range(12,28123-11) if x < proper(x)}
  16. abun_sum = sum(x for x in range(1,28124) if decide(x))
  17. print(abun_sum)
  18. #print(abun_set)
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-23 13:21:06 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2016-6-24 02:03:25 | 显示全部楼层
  1. import time
  2. import itertools
  3. from functools import reduce

  4. def primefactors(n):
  5.     f = 2
  6.     while f * f <= n:
  7.         while not n % f:
  8.             yield f
  9.             n //= f
  10.         f += 1
  11.     if n > 1:
  12.         yield n

  13. t = time.time()

  14. #to get all the abundunt numbers below 28123
  15. s = {i for i in range(1,28124) if sum({reduce(lambda x,y:x*y,item) for num in range(1,len(list(primefactors(i)))) for item in itertools.combinations(list(primefactors(i)),num)})+1 > i}
  16. l = sorted(list(s))

  17. summ_l = sum(range(1,28124))
  18. summ = 0
  19. for i in range(1,28124):
  20.     for j in l:
  21.         if i -j <= 0:
  22.             break
  23.         if j in s and i-j in s:
  24.             summ += i
  25.             break
  26. result = summ_l-summ
  27. print(result)
  28. print(time.time()-t)        
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-24 20:17:50 | 显示全部楼层
不能表示为两个过剩数之和的正整数之和为:4179871
  1. def guoshen(n):
  2.     he = 0
  3.     y = 0
  4.     x = n // 2 + 1
  5.     for i in range(x,0,-1):
  6.         if n % i == 0:
  7.             he += i
  8.             if he > n:
  9.                 y = 1
  10.                 break
  11.     return y

  12. g_list = []
  13. result = 0

  14. for i in range(12,28123):
  15.     if guoshen(i):
  16.         g_list.append(i)

  17. for i in range(1,28124):
  18.     panduan = 1
  19.     for j in g_list:
  20.         if j<i:
  21.             cha = i - j
  22.             if cha in g_list:
  23.                panduan = 0
  24.                break
  25.         else:
  26.             break
  27.     if panduan:
  28.         result += i

  29. print("不能表示为两个过剩数之和的正整数之和为:%d" % result)  
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-25 11:46:06 | 显示全部楼层
  1. #python3.4
  2. import time

  3. t1 = time.perf_counter()
  4. n = 28123
  5. count = n // 2
  6. dict = {}
  7. get = dict.get
  8. for i in range(2, count // 2 + 1):
  9.     for j in range(i, n // i + 1):
  10.         sum_num = i * j
  11.         dict[sum_num] = get(sum_num, 1) + i + (j if j != i else 0)
  12.         pass
  13. #print(dict)
  14. aa = [i for i, j in dict.items() if j > i]
  15. bb = (j + k for i, j in enumerate(aa) for k in aa[i:])
  16. bb = set(bb)
  17. cc = [i for i in range(1, n+1) if i not in bb]
  18. print(sum(cc))
  19. print('%0.9f' % (time.perf_counter() - t1))
复制代码

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-25 14:06:10 | 显示全部楼层
  1. def is_gss(num):
  2.     ret = 1
  3.     for i in range(2, num // 2 + 1):
  4.         if not num % i:
  5.             ret += i
  6.     if ret > num:
  7.         return True
  8.     else:
  9.         return False

  10. gss = []
  11. for i in range(12, 28123):
  12.     if is_gss(i):
  13.         gss.append(i)

  14. ret = []
  15. for i in gss:
  16.     for j in gss:
  17.         if i + j:
  18.             ret.append(i + j)

  19. ret = set(ret)
  20.             
  21. ans = 0
  22. for i in range(1, 28123):
  23.     if i not in ret:
  24.         ans += i

  25. print(ans)
复制代码

4179871

评分

参与人数 1荣誉 +5 鱼币 +5 收起 理由
冬雪雪冬 + 5 + 5 热爱鱼C^_^

查看全部评分

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

使用道具 举报

发表于 2016-6-25 18:07:29 | 显示全部楼层
  1. def d(n):
  2.     # 是否过剩数
  3.     result = set()
  4.     for i in range(2,int(n**.5)+1):
  5.         if not n % i:
  6.             result.update({i, n // i})
  7.     return n > 1 and sum(result) + 1 > n

  8. limite = range(20613)
  9. abdn = []
  10. result = [i for i in limite]
  11. for i in limite:
  12.     if d(i):
  13.         abdn.append(i)
  14.         for e in abdn:
  15.             temp =  i+e
  16.             if temp > 20612:
  17.                 break
  18.             result[temp] = 0

  19. print(sum(result))
复制代码

评分

参与人数 1荣誉 +7 鱼币 +7 收起 理由
冬雪雪冬 + 7 + 7 热爱鱼C^_^

查看全部评分

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-7 18:18

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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