一、从一道题目开始
求整数n以内(含n)的全部亲密数。
说明:如果正整数A的全部因子(包括1,不包括A本身)之和等于B;且正整数B的全部因子(包括1,不包括B本身)之和等于A,A不等于B,则将正整数A和B称为亲密数。
1不和其他数形成亲密数。
编写函数sumElem(),实现统计一个数字的因子之和(包括1,不包括A本身)
【输入形式】
输入整数n
【输出形式】
每一行输出一对亲密数,中间用一个空格隔开。
每一对亲密数只输出一次,小的在前。
各对亲密数按序排序,按亲密数中小的那个数从小到大排序。
【样例输入】
3000
【样例输出】
220 284
1184 1210
2620 2924
解题:
分解这道题的意思,无非对于一个范围内的数字,先产生一个因数列表,对列表元素求和。然后比对在这个范围内有没有一个数A=B的因子列表之和,同时B=A的因子列表之和。这里涉及到如果给定的数值范围过大会出现运行时间过长的问题,所以必须减少一重循环。在找A=B因子之和后,只要B不等于A且B=A因子之和就好了,不用再循环第二重找B。
代码如下:
def sumElem(num):
f=[]
for i in range(1,num):
if num%i==0:
f.append(i)
s=sum(f)
return s #某一个数的因子之和
def panduan(r):
dic={}
for i in range(1,r):
dic[i]=sumElem(i)#设置一个字典,把范围之内的数都放进去,对应的值就是这些数分别的因子之和
ls=[] #用来放结果的列表
for x in dic: #逻辑就是:dic[A],也就是x对应的值(因子和)就是B的值,这里求证字典里有无B,且B与A不同
if dic[x] in dic and dic[dic[x]]==x and dic[x]!=x:
if x<dic[x]:
ls.append((x,dic[x])) #把结果以元组的形式加入列表
else:
ls.append((dic[x],x))
ret=list(set(ls)) #因为遍历到A时和遍历到B时都会把结果加进列表,所以结果是重复的,通过先变成集合,删除重复的元组
ret.sort()
[print (i,j) for i,j in ret] #一种把列表中元组分别格式化打印出来的方法
n=int(input())
panduan(n)
二 列表推导式,不仅用来形成新列表
有时候,我们需要在结果列表中添加元组,得到的结果列表中,元素是元组。而如果题目需要把每个元组分行打印,并且要去除元组的括号和逗号,可以用这样的方式打印:
[print(i,j) for i,j in <tuple>],外面这一层[ ]是不能少的,这一步可以把结果直接打印出来。这本质是列表推导式,for i,j in ret 实际上是遍历了列表中的(i,j)元组,由于print不可以返回一个值,所以这个列表推导式不产生新列表,而直接打印结果。
所以,如果不用列表推导式,可以写成:
for items in li:
print("{} {}".format(items[0],items[1]))