一开始,从2021个结点,已经构建好的二叉树的角度去思考,毫无头绪。
本题要站在构建二叉树过程的角度去思考
首先一个结点都没有,空树,权值为0 ==
只有一个结点时,此时的权值为1==
dp = [0,1]
有两个结点时,循环设左子树的个数为0或1,不同状态下的改结点的权值,并多种状态下不同值的最小值
有三个结点时,循环设左子树的个数为0或1或2,不同状态下的改结点的权值,并多种状态下不同值的最小值
以此类推
其中,左子树的个数设为i,那么右子树的个数就是i-j-1
初始时,空树是权值0,第一个结点的权值为1,其他2020个结点权值为inf 无穷大
dp=[0]+ [1] +[float("inf")]*2020
dp=[0]+ [1] +[float("inf")]*2020
for i in range(1,2022): #遍历结点1~2021
for j in range(i): #遍历结点0~i
dp[i]=min(dp[i],1+2*dp[j]+3*dp[i-j-1]+j*j*(i-j-1))#递推公式
print(dp)
print(dp[2021]) #输出结果:2653631372
由题意qiao的排序交换次数为4 ==> 顺序排序
冒泡排序的最坏情况是初始全部逆序,这样交换次数为
例: 5 4 3 2 1
交换次数为 4 + 3 + 2 + 1,符合公式
找到符合100次的最坏情况为多少个字母
15个字母时,最坏为105次
满足字典序最小,也就是abcdefghijklmno
注:若是字典序最大,也就是从z前往前数15个
倒着写就是onmlkjihggedcba
105比100多了5次,我们反推,正常是,开头字符向后比较,我们这里反向思考,找到交换次数为5的j,把它放到最前面,也就是jonmlkihgfedcba
#代码验证:判断交换次数是否为100次?
s=list("jonmlkihgfedcba")
cnt=0
#冒泡排序
for i in range(len(s)-1):
for j in range(len(s)-1-i):
if s[j]>s[j+1]:
s[j],s[j+1]=s[j+1],s[j]
cnt+=1
print(cnt)
count = 0
for i in range(1,2021):
if '2' in str(i):
count+= 1
print(count)
#1.创建1~100的质数集
def prime(x):
for i in range(2,int(x**0.5)+1):
if x%i==0:
return False
return True
zhishu=[i for i in range(2,101) if prime(i)==True]
#zhishu=[2,3,5,7,11···,97]
#2.计算约数个数
a=[0]*100 #创建计数数组
for i in range(1,101): #遍历1~100
x=i #当前变量赋值
for j in zhishu: #遍历质数数组
while x%j==0: #判断约数
a[j]+=1 #对应计数+1
x//=j #循环条件
#a=[0, 0, 97···0,0]
a=[i for i in a if a!=0]
#[97, 48, 24, 16···]
#3.遍历结果
ans=1
for i in a:
ans*=i+1 #唯一分解定理公式
print(ans) #39001250856960000
s ='tocyjkdzcieoiodfpbgcncsrjbhmugdnojjddhllnofawllbhfiadgdcdjstemphmnjihecoapdjjrprrqnhgccevdarufmliqijgihhfgdcmxvicfauachlifhafpdccfseflcdgjncadfclvfmadvrnaaahahndsikzssoywakgnfjjaihtniptwoulxbaeqkqhfwl'
dp = [1 for i in range(len(s))]
for i in range(len(s)):
for j in range(i):
if s[i] > s[j]:
dp[i] += dp[j]
if s[i] == s[j]:
dp[i] -= dp[j]
print(sum(dp))