问题71-75参见: https://www.jianshu.com/p/e7db7125c148
76、组合1 整数加法
将5写成整数的和有下面6种不同的方式:
1: 4 + 1
2: 3 + 2
3: 3 + 1 + 1
4: 2 + 2 + 1
5: 2 + 1 + 1 + 1
6: 1 + 1 + 1 + 1 + 1
将100写成整数的和有多少种不同的方式。
Python3解答 动态回归思想参见
def DP_Com(exlist,num):
an=[1]+[0]*num
for i in exlist :
for j in range(i,num+1):
an[j]+=an[j-i]
return an[num]
print(DP_Com(list(range(1, 100)),100))
答案:190569291
77、组合2 素数加法
将10写成素数的和有5种不同的方式:
1: 7 + 3
2: 5 + 5
3: 5 + 3 + 2
4: 3 + 3 + 2 + 2
5: 2 + 2 + 2 + 2 + 2
写成素数的和有超过五千种不同的方式最小的数。
Python3解答 动态回归思想参见
def Prime(number):#素数序列
isprime = [False, False] + [True] * (number - 1)
prime = []
for ii in range(2, number + 1):
if isprime[ii]:
prime.append(ii)
for jj in range(ii * 2, number + 1, ii):
isprime[jj] = False
return prime
def DP_Com(exlist,num):#动态规划
an=[1]+[0]*num
for i in exlist :
for j in range(i,num+1):
an[j]+=an[j-i]
return an[num]
count = 0
number = 9
while count <= 5000:
number += 1
count = DP_Com(Prime(number), number)
print(number)
答案:71
78、硬币拆分
记p(n)是将n枚硬币拆分为堆的不同方式数。例如:五枚硬币有7种拆分成堆的不同方式,因此p(5)=7。
1: OOOOO
2: OOOO O
3: OOO OO
4: OOO O O
5: OO OO O
6: OO O O O
7: O O O O O
找出使p(n)能被一百万整除的最小n值。
Python3解答 方法参考:Generalized pentagonal numbers
def Tran(n):
if n == 0:
return 1
else:
return int((3 * n * n - n) / 2)
exlist ={0 : 1}
num = 1
while 1:
n = 1
star = 0
while num - Tran(n) >= 0:
star += int((-1 * (-1) ** (n))) * exlist[num - Tran(n)]
if n <= 0:
n = -n + 1
else:
n = -n
exlist[num] = int(star)
if str(exlist[num])[-6:] == '000000':#被100万整除
break
num += 1
print(num)
print(exlist[num])
答案:最小的n:55374
p(55374)=36325300925435785930832331577396761646715836173633893227071086460709268608053489541731404543537668438991170680745272159154493740615385823202158167635276250554555342115855424598920159035413044811245082197335097953570911884252410730174907784762924663654000000
79、破解密码
网上银行的一种密保手段是向用户询问密码中的任意三位字符。例如:如果用户密码是531278,询问第2、3、5位字符,正确回复应当是317。文件keylog.txt中包含了50个正确回复。
假设三个字符总是按顺序询问的,分析这个文本文件,给出这个未知长度的密码最短的一种可能。
Python3解答
import re
fan=open(r'C:\Users\GWT9\Desktop\keylog.txt')#数据文件
#利用正则表达式
an =[]#存储数据文件
digit = []
while 1:
x=fan.readline()
if len(x) == 0:
break
for ii in x:
if ii not in digit and ii !='\n':
digit.append(ii)
an.append(x)
fan.close()
pattern = []#存储所有正则的格式
for jj in an:
red = r'^(.*%s.*%s.*%s.*)$'%(jj[0], jj[1], jj[2])
if red not in pattern:
pattern.append(red)
#计算开始最小的数,digit存储了这个密码用到的数字,根据此可计算开始匹配的最小的数
num = ''
for istr in sorted(digit):
num += istr
if num[0] == '0':
minnumer = int(num[1] + num[0] + num[2:])
else:
minnumer = int(num)
#开始
sign = 1
while 1:
strnumer = str(minnumer)
for p in pattern:
if not re.compile(p).match(strnumer):#只要匹配不上。匹配的数字就加1
sign = 0
break
if sign == 1:#证明全部匹配上了。
break
minnumer = int(minnumer) + 1
sign = 1
print(minnumer)
答案:73162890
80、平方根展开
众所周知,如果一个自然数的平方根不是整数,那么就一定是无理数。这样的平方根的小数部分是无限不循环的。例如:2的平方根1.41421356237309504880…,它的前100位数字的和是475=1+4+1+…。
对于前100个自然数,求所有无理数平方根的前100位数字的总和。
Python3解答
#方法一:利用python的小数精确库
import decimal#调用系统库
decimal.getcontext().prec = 120 #设置精度
result = 0
for i in range(1, 100):#前100个自然数0-99
sq = i ** 0.5
if sq - int(sq) != 0:#判断是不是完全平方数
sboot = decimal.Decimal(i).sqrt()
for jj in str(sboot)[: 101]:#前100位数字
if jj != '.':
result += int(jj)
print(result)
#方法二:利用Frazer Jarvis's method
def coms(n):#计算n的无理数平方根的前100位数字和
result = ''
a, b = 5 *n, 5
while len(result) < 100:#前100位数字
if a >= b:
a, b = a - b, b + 10
else:
a, b = a * 100, 10 * b - 45
result = str(b)[0 : -2]
sumnum = 0
for jj in result:
sumnum += int(jj)
return sumnum
lastnum = 0
for ii in range(1, 100):
sq = ii ** 0.5
if sq - int(sq) != 0:
lastnum += coms(ii)
print(lastnum)
答案:40886
持续更新,欢迎讨论,敬请关注!!!