Python3 欧拉计划 问题76-80

Python3 欧拉计划 问题76-80_第1张图片
EulerProject.png

问题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

持续更新,欢迎讨论,敬请关注!!!  

你可能感兴趣的:(Python3 欧拉计划 问题76-80)