目录
题目
一、思路分析
二、代码实现
三、总结
对于这个题目,很多人的第一想法就是暴力求解,但会发现运行很久结果都无法出来,甚至报错memory,原因很明显,直接检索的话数的范围太大
很自然的想法就是缩小检索数的范围,观察可发现%11和%17的结果都为0,则数必定为11和17的最小公倍数的倍数,即n=k*11*17(其中k为自然数),但检索范围还是有点大。
这次我们可以针对k做文章,发现11*17%3=1,而11*17*2%3=2,则可以发现11*17*(3k+2)都会满足%3=2,又因为%2=1,即n为奇数,因此k要为奇数。于是我们很自然的就想当k为多少时,满足11*17*(3k+2)%4=1,同理可以不断的进行下去……我们当然希望选取更少的数来判断,因此就需要扩大选取的步长,且最好选取质数(因为非质数有时k会重复)
代码如下(示例):
#找质数的余数之间关系缩小数的范围 这里以%3余2为主体(即3k+2),然后依次循环13,23,37,43,47等缩小k的范围提高运行效率
tmp=[0,0] #记录缩小的范围(起始数和步长)
i=0
for k in range(1,1000000,2): #因为%2=1,所以不能为2的倍数,因此3k+2,k要为奇数
if 187*(3*k+2)%13==10:
tmp[i]=k
i+=1
if i==2:
i=0
break
for k in range(tmp[0],1000000,tmp[1]-tmp[0]):#根据上一步算出来的结果来调整相应的起始数和步长
if 187*(3*k+2)%29==16:
tmp[i]=k
i+=1
if i==2:
i=0
break
for k in range(tmp[0],10000000,tmp[1]-tmp[0]):
if 187*(3*k+2)%37==22:
tmp[i]=k
i+=1
if i==2:
i=0
break
for k in range(tmp[0],100000000,tmp[1]-tmp[0]):
if 187*(3*k+2)%41==1:
tmp[i]=k
i+=1
if i==2:
i=0
break
for k in range(tmp[0],1000000000,tmp[1]-tmp[0]):
if 187*(3*k+2)%47==5:
tmp[i]=k
i+=1
if i==2:
i=0
break
dp=[187*(3*k+2) for k in range(tmp[0],pow(10,14),tmp[1]-tmp[0])]
dic={2: 1, 3: 2, 4: 1, 5: 4, 6: 5, 7: 4, 8: 1, 9: 2, 10: 9, 11: 0,
12: 5, 13: 10, 14: 11, 15: 14, 16: 9, 17: 0, 18: 11, 19: 18,
20: 9, 21: 11, 22: 11, 23: 15, 24: 17, 25: 9, 26: 23, 27: 20,
28: 25, 29: 16, 30: 29, 31: 27, 32: 25, 33: 11, 34: 17, 35: 4,
36: 29, 37: 22, 38: 37, 39: 23, 40: 9, 41: 1, 42: 11, 43: 11,
44: 33, 45: 29, 46: 15, 47: 5, 48: 41, 49: 46}
for n in dp:
for i in range(2,50):
if n%i!=dic[i]:
break
else:
print(n)
break
以上就是今天要讲的内容,暴力模拟很多时候是一个好方法,关键在于如何提高效率。觉得有帮助的朋友可以动动手点个赞哦!