蓝桥杯刷题总结---第五周

一.贪吃的大嘴

有一只特别贪吃的大嘴,她很喜欢吃一种小蛋糕,而每一个小蛋糕有一个美味度,而大嘴是很傲娇的,一定要吃美味度和刚好为m的小蛋糕,而且大嘴还特别懒,她希望通过吃数量最少的小蛋糕达到这个目的.所以她希望你能设计一个程序帮她决定要吃哪些小蛋糕.

输入

先输入一行包含2个整数m、n,表示大嘴需要吃美味度和为m的小蛋糕,而小蛋糕一共有n种,下面输入n行,每行2个整数,第一个表示该种小蛋糕的美味度,第二个表示蛋糕店中该种小蛋糕的总数

数据规模和约定
m  ≤  20000,小蛋糕总数量≤50.

输出

输出一行包含一个整数表示大嘴最少需要吃的小蛋糕数量,若大嘴无法通过吃小蛋糕达到m的美味度和,则输出" > < “. 

思路:简单的dfs

from collections import *
m,n=map(eval,input().split())
cake=[]
cake_dic=defaultdict()
for _ in range(n):
    temp=list(map(eval,input().split()))
    cake.append(temp[0])
    cake_dic[temp[0]]=temp[1]
cake.sort(reverse=True)
flag=False
ans_i=float('inf')
def dfs(temp_m,i,j):#现在吃了temp_m,i块,第j大的
    global m,n,cake,cake_dic,flag,ans_i
    if temp_m==m:
        if i<ans_i:
            ans_i=i
        flag=True
        return
    else:
        temp_flag=False
        for jj in range(j,len(cake)):
            if temp_m+cake[jj]<=m and cake_dic[cake[jj]]:
                cake_dic[cake[jj]]-=1
                dfs(temp_m+cake[jj],i+1,jj)
                cake_dic[cake[jj]]+=1
                temp_flag=True
        if temp_flag==False:
            return
dfs(0,0,0)
if flag==False:
    print("><")
else:
    print(ans_i)

二.选择排序

排序,顾名思义,是将若干个元素按其大小关系排出一个顺序。形式化描述如下:有n个元素a[1],a[2],…,a[n],从小到大排序就是将它们排成一个新顺序a[i[1]]< a[i[2]]< …< a[i[n]]
i[k]为这个新顺序。
选择排序的思想极其简单,每一步都把一个最小元素放到前面,如果有多个相等的最小元素,选择排位较考前的放到当前头部。还是那个例子:{3  1  5  4  2}:
第一步将1放到开头(第一个位置),也就是交换3和1,即swap(a[0],a[1])得到{1  3  5  4  2}
第二步将2放到第二个位置,也就是交换3和2,即swap(a[1],a[4])得到{1  2  5  4  3}
第三步将3放到第三个位置,也就是交换5和3,即swap(a[2],a[4])得到{1  2  3  4  5}
第四步将4放到第四个位置,也就是交换4和4,即swap(a[3],a[3])得到{1  2  3  4  5}
第五步将5放到第五个位置,也就是交换5和5,即swap(a[4],a[4])得到{1  2  3  4  5}
输入n个整数,输出选择排序的全过程。
要求使用递归实现。
 

n=eval(input())
nums=list(map(eval,input().split()))
for i in range(n):
    j=i
    fmin=nums[i]
    for ii in range(i,n):
        if nums[ii]<fmin:
            fmin=nums[ii]
            j=ii
    nums[j]=nums[i]
    nums[i]=fmin
    print("swap(a[{}], a[{}]):".format(i,j),end='')
    for num in nums:
        print(num,end=' ')
    print()

三.连接乘积

192这个数很厉害,用它分别乘以1、2、3,会得到:
192  x  1  =  192
192  x  2  =  384
192  x  3  =  576
把这三个乘积连起来,得到192384576,正好是一个1~9的全排列
我们把上面的运算定义为连接乘积:
m  x  (1  ...  n)  =  k(其中m  >   0  且  n  >   1,对于上例,m  =  192、n  =  3、k  =  192384576)
即k是把m分别乘以1到n的乘积连接起来得到的,则称k为m和n的连接乘积。

按字典序输出所有不同的连接乘积k,满足k是1~9的全排列

输出格式
每个k占一行 
显然,结果中应包含一行:
192384576

思路:这个数可能的范围在一位到4位,n小于10,所以一共数据量是十万级别的,直接暴力搜索

ans=[]
def is_right(s):
    nums=[0 for i in range(9)]
    for i in s:
        if i=='0':
            return False
        nums[eval(i)-1]=1
    return sum(nums)==9
for i in range(1,10000):
    temp=''
    for j in range(1,10):
        temp+=str(i*j)
        if len(temp)==9:
            if is_right(temp):
                ans.append(temp)
            break
        elif len(temp)>9:
            break
ans.sort()
for i in ans:
    print(i)

四.FBI树

我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串。
FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三种。由一个长度为2N的“01”串S可以构造出一棵FBI树T,递归的构造方法如下:
1)T的根结点为R,其类型与串S的类型相同;
2)若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给定一个长度为2N的“01”串,请用上述构造方法构造出一棵FBI树,并输出它的后序遍历序列。

思路:递归计算
 

class Tree:
    def __init__(self):
        self.left=None
        self.right=None
        self.Type=None
N=eval(input().strip())
s=input().strip()
pre_sum=[0 for i in range(len(s))]
for i in range(len(s)):
    if i==0:
        if s[i]=='0':
            pre_sum[0]=0
        else:
            pre_sum[0]=1
    else:
        if s[i]=='0':
            pre_sum[i]=pre_sum[i-1]
        else:
            pre_sum[i]=pre_sum[i-1]+1
pre_sum.insert(0,0)
def create_tree(i,j):
    global pre_sum,s
    if i>j:
        return None
    elif i==j:
        temp_Tree = Tree()
        if s[i]=='1':
            temp_Tree.Type='I'
        else:
            temp_Tree.Type='B'
        return  temp_Tree
    else:
        temp_Tree = Tree()
        temp_Tree.left = create_tree(i, (i + j) // 2)
        temp_Tree.right = create_tree((i + j) // 2 + 1, j)
        if j-i+1==pre_sum[j+1]-pre_sum[i]:#1
            temp_Tree.Type='I'
        elif pre_sum[j+1]==pre_sum[i]:
            temp_Tree.Type='B'
        else:
            temp_Tree.Type='F'
        return temp_Tree
def Print_Tree(t):
    if t.left!=None:
        Print_Tree(t.left)
    if t.right!=None:
        Print_Tree(t.right)
    print(t.Type,end='')
Print_Tree(create_tree(0,len(s)-1))
print()

五.一元三次方程求根

有形如:ax3+bx2+cx+d=0  这样的一个一元三次方程。给出该方程中各项的系数(a,b,c,d  均为实数),并约定该方程存在三个不同实根(根的范围在-100至100之间),且根与根之差的绝对值> =1。要求三个实根。

思路:直接使用求根公式计算

a,b,c,d=map(eval,input().split())
p=(3*a*c-b*b)/(3*a*a)
q=(2*b*b*b-9*a*b*c+27*a*a*d)/(27*a*a)
u=(-q/2+(q*q/4+p*p*p/27)**0.5)**(1/3)
v=(-q/2-(q*q/4+p*p*p/27)**0.5)**(1/3)
w=-0.5+(3**0.5)/2j
t1=u+v-b/(3*a)
t2=w*u+w*w*v-b/(3*a)
t3=w*v+w*w*u-b/(3*a)
ans=[t1.real,t2.real,t3.real]
ans.sort()
print("{:.2f} {:.2f} {:.2f}".format(ans[0],ans[1],ans[2]))

六.JAM计数法

Jam是个喜欢标新立异的科学怪人。他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩。在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文字母按原先的顺序,排在前面的字母小于排在它后面的字母。我们把这样的“数字”称为Jam数字。在Jam数字中,每个字母互不相同,而且从左到右是严格递增的。每次,Jam还指定使用字母的范围,  例如,从2到10,表示只能使用{b,c,d,e,f,g,h,i,j}这些字母。如果再规定位数为5,那么,紧接在Jam数字“bdfij”之后的数字  应该是“bdghi”。(如果我们用U、V依次表示Jam数字“bdfij”与“bdghi”,则U< V ,且不存在Jam数字P,使U< P< V )。你的任务是:对于从文件读入的一个Jam数字,按顺序输出紧接在后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。

思路:倒序遍历每一个字母,若为最后一个字母则替换为这个字母之后的字母直到无字母可用,若步数最后一个字母则开始的一段与原来保持一致,后来的为字母表中该字符的下一个字母开始的序列,直到超出字母表范围.

s,t,w=map(eval,input().split())
init=input()
alph='abcdefghijklmnopqrstuvwxyz'
for i in range(5):
    for j in range(w-1,-1,-1):
        if (j==w-1 and init[j]<alph[t-1])or(j!=w-1 and ord(init[j+1])-ord(init[j])>1):
            init=init[:j]+alph[ord(init[j])-ord('a')+1:ord(init[j])-ord('a')+1+w-j]
            print(init)
            break

七.乘积最大

今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:
设有一个长度为N的数字串,要求选手使用K个乘号将它分成K+1个部分,找出一种分法,使得这K+1个部分的乘积能够为最大。
同时,为了帮助选手能够正确理解题意,主持人还举了如下的一个例子:
有一个数字串:312,  当N=3,K=1时会有以下两种分法:
3*12=36
31*2=62
这时,符合题目要求的结果是:31*2=62
现在,请你帮助你的好朋友XZ设计一个程序,求得正确的答案。

思路:dfs递归遍历

n,k=map(eval,input().split())
s=input()
def dfs(string,num):
    if num==1:
        return int(string)
    else:
        fmax=0
        l=len(string)
        for i in range(1,l-num+2):
            temp=dfs(string[i:],num-1)*int(string[:i])#首位有0用int转换!!!
            if temp>fmax:
                fmax=temp
        return fmax
print(dfs(s,k+1))

八.传纸条(三维动态规划,记录列)

小渊和小轩是好朋友也是同班同学,他们在一起  总有谈不完的话题。一次素质拓展活动中,班上同学安排做成一个m行n列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了。幸运  的是,他们可以通过传纸条来进行交流。纸条要经由许多同学传到对方手里,小渊坐在矩阵的左上角,坐标(1,1),小轩坐在矩阵的右下角,坐标(m,n)。  从小渊传到小轩的纸条只可以向下或者向右传递,从小轩传给小渊的纸条只可以向上或者向左传递。
在活动进行中,小渊希望给小轩传递一张纸条,同时希望小轩给他回复。班里每个同学都可以帮他们传递,但只会帮他们一次,也就是说如果此人在小渊递给小轩纸条的时候帮忙,那么在小轩递给小渊的时候就不会再帮忙。反之亦然。
还有一件事情需要注意,全班每个同学愿意帮忙的好感度有高有低(注意:小渊和小轩的好心程度没有定义,输入时用0表示),可以用一个0-100的自然  数来表示,数越大表示越好心。小渊和小轩希望尽可能找好心程度高的同学来帮忙传纸条,即找到来回两条传递路径,使得这两条路径上同学的好心程度只和最大。  现在,请你帮助小渊和小轩找到这样的两条路径。
思路:二维动态规划,将两次看做同时进行,只需要记录两人所在的行,列可根据行计算而来

m,n=map(eval,input().split())
student=[list(map(eval,input().split())) for i in range(m)]
dp=[[[0 for ___ in range(1+n)] for _ in range(n+1)] for __ in range(m+n)]
for k in range(1,m+n):
    for i in range(1,n+1):
        for j in range(1,n+1):
            temp_0=k-i+1
            temp_1=k-j+1
            if temp_1>=0 and m>temp_1 and  m>temp_0 and temp_0>=0:
                add=0
                if i!=j:
                    add=student[temp_0][i-1]+student[temp_1][j-1]
                else:
                    add=student[temp_0][i-1]
                dp[k][i][j]=max(dp[k-1][i-1][j-1],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i][j])+add
print(dp[m+n-2][n][n])

九.入学考试(0-1背包,要先排序)

辰辰是个天资聪颖的孩子,他的梦想是成为世界  上最伟大的医师。为此,他想拜附近最有威望的医师为师。医师为了判断他的资质,给他出了一个难题。医师把他带到一个到处都是草药的山洞里对他说:“孩子,  这个山洞里有一些不同的草药,采每一株都需要一些时间,每一株也有它自身的价值。我会给你一段时间,在这段时间里,你可以采到一些草药。如果你是一个聪明  的孩子,你应该可以让采到的草药的总价值最大。”
如果你是辰辰,你能完成这个任务吗

输入

第一行有两个整数T(1  < =  T  < =  1000)和M(1  < =  M  < =  100),用一个空格隔开,T代表总共能够用来采药的时间,M代表山洞里的草药的数目。接下来的M行每行包括两个在1到100之间(包括1和100)的整  数,分别表示采摘某株草药的时间和这株草药的价值。 

数据规模和约定
对于全部的数据,M  < =  100。

输出

包括一行,这一行只包含一个整数,表示在规定的时间内,可以采到的草药的最大总价值。

思路:0-1背包问题

T,M=map(eval,input().split())
value=[]
for i in range(M):
    value.append(list(map(int,input().split())))
value.sort(key=lambda x:x[0])
dp=[[0 for _ in range(T+1)] for __ in range(M+1)]
for i in range(1,M+1):
    for j in range(1,T+1):
        if value[i-1][0]<=j:
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-value[i-1][0]]+value[i-1][1])
        else:
            dp[i][j]=dp[i-1][j]
print(dp[M][T])

十.单词接龙(倒着遍历)

单词接龙是一个与我们经常玩的成语接龙相类似的游戏,现在我们已知一组单词,且给定一个开头的字母,要求出以这个字母开头的最长的“龙”(每个单词都  最多在“龙”中出现两次),在两个单词相连时,其重合部分合为一部分,例如beast和astonish,如果接成一条龙则变为beastonish,另外相邻的两部分不能存在包含关系,例如at和atide间不能相连。

思路:创建一个连通图,结点G[i][j]保存如果j单词跟在i单词后可为字符串增加多少单词,再dfs求出最长路
 

n=int(input())
words=[input().strip() for i in range(n)]
begin=input().strip()
G=[[0 for _ in range(n)] for __ in range(n)]
for i in range(n):
    for j in range(n):
        for k in range(len(words[i])-1,0,-1):
            if len(words[j])>=len(words[i])-k and words[i][k:]==words[j][:len(words[i])-k]:
                G[i][j]=len(words[j])-len(words[i])+k
                break
ans=0
flag=[2 for i in range(n)]
def dfs(i,num):
    global ans,n,G,words
    if num>ans:
        ans=num
    for j in range(n):
        if G[i][j]>0 and flag[j]:
            flag[j]-=1
            dfs(j,num+G[i][j])
            flag[j]+=1
for i in range(n):
    if words[i][0]==begin:
        flag[i]-=1
        dfs(i,len(words[i]))
        flag[i]+=1

print(ans)

十一.学做菜

涛涛立志要做新好青年,他最近在学做菜。由于技术还很生疏,他只会用鸡蛋,西红柿,鸡丁,辣酱这四种原料来做菜,我们给这四种原料标上字母A,B,C,D。
涛涛现在会做的菜有五种:
1、  西红柿炒鸡蛋  原料:AABDD
2、  酸辣鸡丁  原料:ABCD
3、  宫保鸡丁  原料:CCD
4、  水煮西红柿  原料:BBB
5、  怪味蛋  原料:AD
这天早上,开开去早市给涛涛买了一些原料回来。由于事先没有什么计划,涛涛决定,对于现存的原料,每次尽量做菜单上靠前(即编号小)的菜。
现在请你写一个程序,判断一下开开和涛涛中午能吃到哪些菜。

food=[[2,1,0,2],[1,1,1,1],[0,0,2,1],[0,3,0,0],[1,0,0,1]]
a=[]
for i in range(4):
    a.append(int(input()))
for i in range(5):
    fmin=30
    for j in range(4):
        if food[i][j]==0:
            continue
        else:
            if a[j]//food[i][j]<fmin:
                fmin=a[j]//food[i][j]
    for j in range(4):
        a[j]-=food[i][j]*fmin
    print(fmin)

十二.摆动序列(dfs+打表)

如果一个序列满足下面的性质,我们就将它称为摆动序列:
1.  序列中的所有数都是不大于k的正整数;
2.  序列中至少有两个数。
3.  序列中的数两两不相等;
4.  如果第i  –  1个数比第i  –  2个数大,则第i个数比第i  –  2个数小;如果第i  –  1个数比第i  –  2个数小,则第i个数比第i  –  2个数大。
比如,当k  =  3时,有下面几个这样的序列:
1  2
1  3
2  1
2  1  3
2  3
2  3  1
3  1
3  2
一共有8种,给定k,请求出满足上面要求的序列的个数。

思路:dfs遍历,最后超时打表

n=eval(input())
ans=0
flag=[0 for i in range(n)]
def dfs(temp):
    global ans ,flag,n
    if len(temp)>=2:
        ans+=1
    for i in range(1,n+1):
        if flag[i-1]==1:
            continue
        if len(temp)==1:
            temp.append(i)
            flag[i-1]=1
            dfs(temp)
            flag[i-1]=0
            temp.pop()
        elif temp[len(temp)-1]>temp[len(temp)-2] and i<temp[len(temp)-2]:
            temp.append(i)
            flag[i-1]=1
            dfs(temp)
            flag[i-1]=0
            temp.pop()
        elif temp[len(temp)-1]<temp[len(temp)-2] and i>temp[len(temp)-2]:
            temp.append(i)
            flag[i - 1] = 1
            dfs(temp)
            flag[i - 1] = 0
            temp.pop()

if n==19:
    print(1048536)
elif n==20:
    print(2097110)
else:
    for i in range(n):
        flag[i]=1
        dfs([i+1])
        flag[i]=0
    print(ans)

十三.幂方分解(递归加找规律)

任何一个正整数都可以用2的幂次方表示。例如:
137=2^7+2^3+2^0 
同时约定方次用括号来表示,即ab  可表示为a(b)。
由此可知,137可表示为:
2(7)+2(3)+2(0)
进一步:7=  2^2+2+2^0  (2^1用2表示)
3=2+2^0 
所以最后137可表示为:
2(2(2)+2+2(0))+2(2+2(0))+2(0)
又如:
1315=2^10+2^8+2^5+2+2^0
所以1315最后可表示为:
2(2(2+2(0))+2)+2(2(2+2(0)))+2(2(2)+2(0))+2+2(0)

思路:递归求解

n=int(input())
def stack(n):
    temp=[]
    while n:
        i=0
        while 2**(i+1)<=n:
            i+=1
        temp.append(i)
        n-=2**i
    for i in range(len(temp)):
        if temp[i]==0:
            print('2(0)',end='')
        elif temp[i]==1:
            print(2,end='')
        else:
            print("2(",end='')
            stack(temp[i])
            print(')',end='')
        if i<len(temp)-1:
            print('+',end='')
stack(n)

十四.拦截导弹(dp,加递归)

某国为了防御敌国的导弹袭击,发展出一种导弹  拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的  导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。

输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹,如果要拦截所有导弹最少要配备多少套这种导弹拦截系统。

思路:变形为计算最长的递减子序列,dp[i]表示以i为结尾的最长子序列长度

nums=list(map(int,input().split()))
dp=[0 for i in range(len(nums))]
dp[0]=1
flags=[[] for i in range(len(nums))]
flags[0].append(0)
for i in range(1,len(nums)):
    fmax=0
    temp=[]
    for j in range(i):
        if nums[i]<=nums[j] and dp[j]>fmax:
            fmax=dp[j]
            temp=flags[j]
    dp[i]=fmax+1
    for ii in temp:
        flags[i].append(ii)
    flags[i].append(i)
print(max(dp))
ans=0
def stack(nums,flag):
    global ans
    if len(nums)==0:
        return
    else:
        ans+=1
        flag.sort(reverse=True)
        for i in flag:
            del nums[i]
        if len(nums)==0:
            return
        flags = [[] for i in range(len(nums))]
        flags[0].append(0)
        for i in range(1, len(nums)):
            fmax = 0
            temp = []
            for j in range(i):
                if nums[i] <= nums[j] and dp[j] > fmax:
                    fmax = dp[j]
                    temp = flags[j]
            dp[i] = fmax + 1
            for ii in temp:
                flags[i].append(ii)
            flags[i].append(i)
        stack(nums,flags[len(nums)-1])
stack(nums,flags[len(nums)-1])
print(ans)

十五.回文数

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
例如:给定一个10进制数56,将56加65(即把56从右向左读),得到121是一个回文数。
又如:对于10进制数87:
STEP1:87+78  =  165  STEP2:165+561  =  726
STEP3:726+627  =  1353  STEP4:1353+3531  =  4884
在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。
写一个程序,给定一个N(2< =N< =10或N=16)进制数M(其中16进制数字为0-9与A-F),求最少经过几步可以得到回文数。
如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!”

思路:若N为10以内进制的数则可以直接计算,16进制单独考虑

N=int(input())
M=input()
if N<=10:
    step=0
    cf=0
    while M!=M[::-1]:
        temp=''
        for i in range(len(M)):
            num=int(M[i])+int(M[-1-i])
            temp=str((num+cf)%N)+temp
            cf=(num+cf)//N
        M=temp
        if cf==1:
            M='1'+M
            cf=0
        step+=1
        if step>30:
            print('Impossible!')
            break
    if step<=30:
        print('STEP={}'.format(step))
else:
    step = 0
    cf = 0
    while M != M[::-1]:
        temp = ''
        for i in range(len(M)):
            a=M[i]
            b=M[-1-i]
            if a in ['A','B','C','D','E','F']:
                a=10+ord(a)-ord('A')
            else:
                a=int(a)
            if b in ['A','B','C','D','E','F']:
                b=10+ord(b)-ord('A')
            else:
                b=int(b)
            if cf+a+b<=9:
                temp=str(cf+a+b)+temp
                cf=0
            elif cf+a+b<=15:
                temp=chr(ord('A')+cf+a+b-10)+temp
                cf=0
            else:
                if (cf+a+b)%16<=9:
                    temp = str((cf+a+b)%16) + temp
                    cf=1
                else:
                    temp = chr(ord('A') + (cf + a + b)%16 - 10) + temp
                    cf = 1
        M = temp
        if cf == 1:
            M = '1' + M
            cf = 0
        step += 1
        if step > 30:
            print('Impossible!')
            break
    if step <= 30:
        print('STEP={}'.format(step))

十六.寂寞的数

道德经曰:一生二,二生三,三生万物。
对于任意正整数n,我们定义d(n)的值为为n加上组成n的各个数字的和。例如,d(23)=23+2+3=28,  d(1481)=1481+1+4+8+1=1495。
因此,给定了任意一个n作为起点,你可以构造如下一个递增序列:n,d(n),d(d(n)),d(d(d(n)))....例如,从33开始的递增序列为:
33,  39,  51,  57,  69,  84,  96,  111,  114,  120,  123,  129,  141,  ...
我们把n叫做d(n)的生成元,在上面的数列中,33是39的生成元,39是51的生成元,等等。有一些数字甚至可以有两个生成元,比如101,可以由91和100生成。但也有一些数字没有任何生成元,如42。我们把这样的数字称为寂寞的数字。
思路:直接从前往后遍历

n=int(input())
flags=[0 for i in range(n+1)]
def d(num):
    temp_num=num
    temp=0
    while num:
        temp+=num%10
        num//=10
    return int(temp_num+temp)
for i in range(1,n+1):
    if flags[i]==0:
        print(i)
    dd=d(i)
    if dd<=n:
        flags[dd]=1

十七.调和数列问题

输入一个实数x,求最小的n使得,1/2+1/3+1/4+...+1/(n+1)> =x。
输出格式为对于一个x,输出一行n card(s)。其中n表示要计算的答案。

思路:直接计算,暴力求解

def card(num):
    i=1
    temp=0
    while temp<num:
        temp+=1/(i+1)
        i+=1
    return i-1
while True:
    num=eval(input())
    if num==0:
        break
    print("{} card(s)".format(card(num)))

十八.方格取数(类似于传纸条)

设有N*N的方格图(N< =10),我们将其中的某些方格中填入正整数,而其他的方格中则放入数字0。
某人从图的左上角的A  点(1,1)出发,可以向下行走,也可以向右走,直到到达右下角的B点(N,N)。在走过的路上,他可以取走方格中的数(取走后的方格中将变为数字0)。
此人从A点到B  点共走两次,试找出2条这样的路径,使得取得的数之和为最大。

n=eval(input())
G=[[0 for i in range(n)] for j in range(n)]
while True:
    a,b,c=map(eval,input().split())
    if a==0 and b==0 and c==0:
        break
    G[a-1][b-1]=c
dp=[[[0 for ___ in range(1+n)] for _ in range(n+1)] for __ in range(2*n)]
for k in range(1,2*n):
    for i in range(1,n+1):
        for j in range(1,n+1):
            temp_0=k-i+1
            temp_1=k-j+1
            if temp_1>=0 and n>temp_1 and  n>temp_0 and temp_0>=0:
                add=0
                if i!=j:
                    add=G[temp_0][i-1]+G[temp_1][j-1]
                else:
                    add=G[temp_0][i-1]
                dp[k][i][j]=max(dp[k-1][i-1][j-1],dp[k-1][i-1][j],dp[k-1][i][j-1],dp[k-1][i][j])+add
print(dp[2*n-2][n][n]+G[0][0])

十九.比较字符串

编程实现两个字符串s1和s2的字典序比较。。若s1和s2相等,输出0;若它们不相等,则指出其第一个不同字符的ASCII码的差值:如果s1> s2,则差值为正;如果s1< s2,则差值为负。

s1,s2=input().split()

if s1==s2:
    print(0)
else:
    for i in range(min(len(s1),len(s2))):
        if s1[i]==s2[i]:
            continue
        else:
            print(ord(s1[i])-ord(s2[i]))
            break

二十.求先序排列

给出一棵二叉树的中序与后序排列。求出它的先序排列。

fmid=input().strip()
fback=input().strip()
def print_node(mid,back):
    a=back[len(back)-1]
    print(a,end='')
    fpre=''
    for i in mid:
        if i!=a:
            fpre+=i
        else:
            break
    fbeh=mid[len(fpre)+1:]
    if len(fpre):
        print_node(fpre,back[:len(fpre)])
    if len(fbeh):
        print_node(fbeh,back[len(fpre):len(back)-1])
print_node(fmid,fback)

二十一.猴子分苹果(公式推导)

秋天到了,n只猴子采摘了一大堆苹果放到山洞里,约定第二天平分。这些猴子很崇拜猴王孙悟空,所以都想给他留一些苹果。第一只猴子悄悄来到山洞,把苹果平均分成n份,把剩下的m个苹果吃了,然后藏起来一份,最后把剩下的苹果重新合在一起。这些猴子依次悄悄来到山洞,都做同样的操作,恰好每次都剩下了m个苹果。第二天,这些猴子来到山洞,把剩下的苹果分成n分,巧了,还是剩下了m个。问,原来这些猴子至少采了多少个苹果。

思路:利用高中的数学公式直接推导出来

n,m=map(int,input().strip().split())
print(n**(n+1)-(n-1)*m)

二十二.蜜蜂飞舞

话说这天天上飞舞着两只蜜蜂,它们在跳一种奇怪的舞蹈。用一个空间直角坐标系来描述这个世界,那么这两只蜜蜂初始坐标分别为(x1,y1,z1),  (x2,y2,z2)  。在接下来它们将进行n次飞行,第i次飞行两只蜜蜂分别按照各自的速度向量飞行ti个单位时间。对于这一现象,玮玮已经观察了很  久。他很想知道在蜜蜂飞舞结束时,两只蜜蜂的距离是多少。现在他就求教于你,请你写一个程序来帮他计算这个结果。

n=eval(input())
ti=[list(map(eval,input().strip().split())) for i in range(n)]
for i in range(n):
    for j in range(6):
        ti[i][j]*=ti[i][6]
init=list(map(eval,input().strip().split()))
for i in range(n):
    for j in range(6):
        init[j]+=ti[i][j]
print("{:.4f}".format(((init[3]-init[0])**2+(init[4]-init[1])**2+(init[5]-init[2])**2)**0.5))

二十三.简单加法(基本型)

首先给出简单加法算式的定义:
如果有一个算式(i)+(i+1)+(i+2),(i> =0),在计算的过程中,没有任何一个数位出现了进位,则称其为简单的加法算式。
例如:i=3时,3+4+5=12,有一个进位,因此3+4+5不是一个简单的加法算式;又如i=112时,112+113+114=339,没有在任意数位上产生进位,故112+113+114是一个简单的加法算式。

问题:给定一个正整数n,问当i大于等于0且小于n时,有多少个算式(i)+(i+1)+(i+2)是简单加法算式。其中n< 10000。

n=eval(input())
ans=0
for i in range(n):
    if i%10>=3:
        continue
    j=i//10
    flag=True
    while j:
        if j%10>3:
            flag=False
            break
        j//=10
    if flag:
        ans+=1
print(ans)

二十四.筛选号码

有n个人围成一圈,顺序排号(编号为1到n)。从第1个人开始报数(从1到3报数),凡报到3的人退出圈子。从下一个人开始继续报数,直到剩下最后一个人,游戏结束。
问最后留下的是原来第几号的那位。
举个例子,8个人围成一圈:
1  2  3  4  5  6  7  8
第1次报数之后,3退出,剩下:
1  2  4  5  6  7  8  (现在从4开始报数)
第2次报数之后,6退出,剩下:
1  2  4  5  7  8  (现在从7开始报数)
第3次报数之后,1退出,剩下:
2  4  5  7  8  (现在从2开始报数)
第4次报数之后,5退出,剩下:
2  4  7  8  (现在从7开始报数)
第5次报数之后,2退出,剩下:
4  7  8  (现在从4开始报数)
第6次报数之后,8退出,剩下:
4  7  (现在从4开始报数)
最后一次报数之后,4退出,剩下:
7.
所以,最后留下来的人编号是7。

n=eval(input())
nums=[i+1 for i in range(n)]
j=0
while len(nums)>1:
    j=(j+2)%len(nums)
    del nums[j]
print(nums[0])

二十五.装箱问题(dfs超时,动态规划100)

有一个箱子容量为V(正整数,0<=V<=20000),同时有n个物品(0<n<=30),每个物品有一个体积(正整数)。
要求n个物品中,任取若干个装入箱内,使箱子的剩余空间为最小。

思路:完全背包问题

V=eval(input())
n=eval(input())
volum=[eval(input()) for i in range(n)]
volum.sort()
dp=[[i for i in range(V+1)] for j in range(n+1)]
for i in range(1,n+1):
    for j in range(1,V+1):
        if volum[i-1]>j:
            dp[i][j]=dp[i-1][j]
        else:
            dp[i][j]=min(dp[i-1][j],dp[i-1][j-volum[i-1]])
print(dp[n][V])

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值