求相亲数

【问题描述】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

如果有两个正整数a和b,a的所有除本身以外的因数之和等于b,b的所有除本身以外的因数之和等于a,则称a,b是一对相亲数。请输出10000以内的相亲数对。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

求相亲数输出结果:liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

[(284,220),(1210,1184),(2924,2620),(5564,5020),(6368,6232)]liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

【题前思考】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

根据问题描述,填写表5-2-1。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

表5-2-1 问题分析liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

求相亲数liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

【解题思路】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

从问题描述来看,判断两个数是否是相亲数,主要操作就是分别求它们的约数之和。为避免重复计算,用一个列表sf来表示约数之和。为了表示上的方便,约定整数i的约数之和保存在a[i]中。这样规定之后,相亲数的表示就比较方便了。只要i==a[a[i]],那么i和a[i]就是一对相亲数。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

【程序代码】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

求相亲数liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

求相亲数liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

【代码分析】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

①:定义局部函数sumfactor(m)用于求m的约数之和。因为它定义在函数amicable(n)内部,所以只有在amicable(n)内才能调用这个函数。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

②:sum(j for j in range(1,m)if m%j==0)使用生成器求m的约数之和。如果表达式j for j in range(1,m)if m%j==0用[ ]括起来,它就是列表推导式,表达式会一次性产生所有值作为列表的项保存到内存中。像本例中的这种用法,用( )括起来或者不用( )括起来,它就是生成器,生成器与列表推导式的最大区别是它不会把项一次性产生出来,而是取一个生成一个,它比列表推导式更省内存。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

③:使用列表推导式产生各个数的约数之和,保存规则就是将i的约数之和保存到a[i]中。sumfactor(x)if x>1 else x表示0的约数之和为0,1的约数之和为1,其他数的约数之和用局部函数sumfactor(x)求取。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

④:[(i,a[i])for i in range(2,n+1)if a[i]<i and i==a[a[i]]]使用列表推导式筛选相亲数对。if a[i]<i and i==a[a[i]]中,a[i]<i既可以防止a[a[i]]越界,又可以防止重复输出和输出完全数,i==a[a[i]]是判断相亲数的条件。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

【优化提升】liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

上例中给出的程序虽然简单,但是在求约数和时速度比较慢,而且求约数和还是关键代码,运行次数非常多。所以,要提高整个程序的运行速度,关键在于提高求约数和的速度。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

我们经过观察会发现,如果j是m的约数,那么m//j肯定也是m的约数,因为此时j*m//j==m。采用这个方法,可以减少一半的判断。为了避免重复要求j<=求相亲数,此外还需要考虑完全平方数的问题。优化后的代码如下:liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

求相亲数liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

表达式s if root*root!=m else s-root表示对完全平方数要减去一个平方根,这是因为当m是完全平方数且j==root的时候,j和m//j值相同,平方根被多加了一次。liT100150满分答卷(100150.com)-青少年编程等级考试及竞赛题库

关 键 词

相亲数

相关教程

提示声明

  • 免责声明:本站资源均来自网络或者用户投稿,仅供用于学习和交流:如有侵权联系删除!

猜你喜欢