Blue Bridge Cup Day 19 (Python) (Day 2 of Crazy Questions)

Question type:

1. Thinking questions/Miscellaneous questions: Mathematical formulas, analyzing the meaning of questions, finding patterns

2. BFS/DFS: wide search (recursive implementation), deep search (deque implementation)

3. Simple number theory: modulus, prime number (only need to judge to int (sqrt (n)) + 1), gcd, lcm, fast exponentiation (bit operation shift operation), large number decomposition (decomposition into the product of prime numbers)

4. Simple graph theory: shortest path (one-to-many (Dijstra, adjacent table, matrix implementation), many-to-many (Floyd, matrix implementation)), minimum spanning tree (and search set implementation)

5. Simple string processing: it is best to switch to list operations

6. DP: Linear DP, longest common subsequence, 0/1 knapsack problem, longest continuous string, largest increasing substring

7. Basic algorithms: binary, greedy, combination, permutation, prefix sum, difference

8. Basic data structures: queues, sets, dictionaries, strings, lists, stacks, trees

9. Commonly used modules: math, datetime, set the maximum recursion depth in sys (sys.setrecursionlimit(3000000)), collections.deque (queue), itertools.combinations (list, n) (combination), itertools.permutations (list, n) (permutation) heapq (small top heap)

Table of contents

1. Unary cubic equation solution (binary, formatted output)

2. Solve the cube root (dichotomy)

3. Divide chocolate (divided, pay attention to the two templates of Divided)

4. Flip a coin (greedy)

5. Chocolate (greedy) 

6. Shunzi date (thinking questions, careful, hand count)

7. Product trailing zero (large number operation or large number decomposition)

8. Sum of Squares (String Operation)

9. Happy Driver (Greedy)

10. Blue peptide subsequence (DP, longest common subsequence)

11. Chorus formation (longest increasing subsequence)

12. String edit distance (DP, classic problem DP)

13. Xiaoming's knapsack 1 (classic 0/1 knapsack problem DP)

14. Longest common subsequence (template question)

15. The longest continuous increasing subsequence (DP template)


1. Unary cubic equation solution (binary, formatted output)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

a,b,c,d = map(float,input().split())
def f(x):
   return x*x*x*a+x*x*b+x*c+d

ans=[]
for i in range(-100,100):
   if f(i)==0:
      ans.append(i)
   if f(i)*f(i+1)<0:  # 在(i,i+1)内有根
      l=i;r=i+1
      while(r-l>=0.001):  # 保留精度,2位小数,注意循环条件
         mid=(l+r)/2
         if f(l)*f(mid)<0:
            r=mid
         else:
            l=mid
      ans.append(l)
if f(100)==0:
   ans.append(100)
for i in ans:
   print("{:.2f}".format(i),end=' ')

It can be regarded as a sub-question, which mainly examines the use of dichotomy, and at the same time boundary processing, that is, do not miss the interval range, and pay attention to formatting the output statement.

2. Solve the cube root (dichotomy)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

T=int(input())
for i in range(T):
   n=int(input())
   for i in range(100000):
      if i**3==n:   # 优先判定是否相等,结果为整数
         print('{:.3f}'.format(i))
         break
      elif i**3>n:  # 最后的结果为小数,通过二分处理
         left=i-1;right=i;
         while(right-left>0.00001):
            mid=(left+right)/2
            if(mid**3>n):
               right=mid
            else:
               left=mid
         print('{:.3f}'.format(l))
         break

         

Meals and points are given away, and the real number dichotomy question does not need to consider the problem of adding one minus one on the boundary. For the accuracy problem, a while statement is enough. For example, if two decimal places are reserved, then the statement is while (right - left) >= 0.001 

3. Divide chocolate (divided, pay attention to the two templates of Divided)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

n,k = map(int,input().split())
save = [] #存放巧克力
Max=1
for i in range(n):
   temp=list(map(int,input().split()))
   Max=max(max(temp),Max)  # 记录大巧克力边长,之后用于二分
   save.append(temp)


def check(i):
   count=0
   for a,b in save:
      count+=(a//i)*(b//i)
   if count>=k:
      return True
   else:
      return False
left=1
right=Max
while(left<right):  # 找<=x的第一个
   
   mid=(left+right+1)//2
   #print(left,mid,right)
   #print('-'*40)
   if check(mid):
      left=mid
   else:
      right=mid-1
print(left)
#print(right)
#print(mid)


'''
2 10
6 5
5 6
测试结果
1 4 6
----------------------------------------
1 2 3
----------------------------------------
2 3 3
----------------------------------------
2
2
3

'''

This is not a dichotomy of real numbers. You need to convert the problem into a dichotomy problem to solve it. Pay attention to the different usage of the two dichotomy templates. When you are looking for the first one <=x, you need to set mid=(left+right+1) //2, find the first one >=x, mid=(right+left)//2.

two bipartite templates

Find the first one >=x, mid=(low+high)//2

a=[0,3,5,7,9,11,13]
# [0,1,2,3,4,5,6]
# low = 0 high =6 mid =3  ----->   low=4  high =6
# low = 4 high =6 mid =5  ----->   low=4  high =5
# low = 4 high =5 mid =4  ----->   low=5  high =5
# break   low=high=5
# 找的是靠右的那一个
low=0
high=len(a)-1
def search(low,high,x):  # 查找的是后一个
    while (low<high):
        mid =(low+high)//2   # (2+3)//2=2  偏左
        if (a[mid]>=x):
            high=mid
        else:
            low=mid+1
    print(a[low])
    print(a[high])
search(low,high,10)  # 查找结果10
 

Find the first one <=x, mid=(low+high+1)//2 

a=[0,3,5,7,9,11,13]
# [0,1,2,3,4,5,6]
# low = 0 high =6 mid =3  ----->   low=3  high =6
# low = 3 high =6 mid =5  ----->   low=3  high =4
# low = 3 high =4 mid =4  ----->   low=4  high =4
# break   low=high=4
# 找的是靠左的那一个
low=0
high=len(a)-1
def search(low,high,x):  # 查找的是前一个
    while (low<high):
        mid =(low+high+1)//2   # (2+3+1)//2=3  偏右
        if (a[mid]<=x):
            low=mid
        else:
            high=mid-1
    print(a[low])
    print(a[high])
search(low,high,10)  # 查找结果10
 
 

4. Flip a coin (greedy)

 

s = input()
t = input()
cnt = 0
for i in range(len(s) - 1):
   if s[i] != t[i]:
       if s[i + 1] == '*':
           s = s[:i + 1] + 'o' + s[i + 2:]
       else:
           s = s[:i + 1] + '*' + s[i + 2:]
       cnt += 1
print(cnt)

The point is how to think that this is a greedy problem, rely on luck, if you can’t figure it out, just follow the greedy way, and the cycle of violence

5. Chocolate (greedy) 

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)


x,n=map(int,input().split())  # 天数,巧克力种类数
#day=[0]*(x+1)  #记录吃什么
thing =[]
for i in range(1,n+1):  # 存储商品
   thing.append(list(map(int,input().split())))
ans=0
thing.sort(key=lambda x:x[0] )  # 按单价从小到大排序
thing=[0]+thing  # 转为下标从一开始

# 开始分配每天的食物    thing-》 [单价,保质期,数量]
for i in range(1,x+1): # 遍历天数
   for j in range(1,n+1):  # 遍历货物
      if thing[j][1]>=i and thing[j][2]>0:  # 没过保质期且还有剩余
         #print(j)
         #day[i]=j    
         ans+=thing[j][0]  # 第i天选第j类食物
         thing[j][2]-=1  # 用了一个需要减一
         break
if ans==0:
  print(-1)
else:
  print(ans)


# 没有用到记录数组,直接遍历的过程中就可以算出答案然后进行输出

The difficulty of the mid-range topic, it feels like a greedy idea, and then just do it according to the requirements of the topic, pay attention to the convenience of processing, you can switch the subscript, that is, start processing from 1, the subscript starts from 1, sometimes you need to record the array, sometimes you don’t , you need to pay attention to it in the process of writing code.

6. Shunzi date (thinking questions, careful, hand count)

 

 For the number of hands, it is enough to enumerate all possible situations. Be careful, don’t rush, count all the situations, it is considered as a sub-question, mainly to understand the meaning of the question

7. Product trailing zero (large number operation or large number decomposition)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

# 因为只有2,5有用,所以只记录2和5的数量
count1=0
count2=0

s="""5650 4542 3554 473 946 4114 3871 9073 90 4329 
2758 7949 6113 5659 5245 7432 3051 4434 6704 3594 
9937 1173 6866 3397 4759 7557 3070 2287 1453 9899 
1486 5722 3135 1170 4014 5510 5120 729 2880 9019 
2049 698 4582 4346 4427 646 9742 7340 1230 7683 
5693 7015 6887 7381 4172 4341 2909 2027 7355 5649 
6701 6645 1671 5978 2704 9926 295 3125 3878 6785 
2066 4247 4800 1578 6652 4616 1113 6205 3264 2915 
3966 5291 2904 1285 2193 1428 2265 8730 9436 7074 
689 5510 8243 6114 337 4096 8199 7313 3685 211"""
save=list(map(int,s.split()))
#print(save)
for i in save:
   while i%2==0:
      count1+=1
      i=i//2
   while i%5==0:
      count2+=1
      i=i//5

print(min(count1,count2))

 Python can handle large numbers, directly separate strings for multiplication, and finally count how many zeros there are. It can be converted into strings or lists for statistics, or can be counted by taking the remainder of integers.

Or decompose the integer into 2, 5, see who has less number, how many 0s

8. Sum of Squares (String Operation)

Send sub-questions, directly traverse 1-2019, convert it into a string to determine whether the number exists in these numbers, and then square the summation

 9. Happy Driver (Greedy)

 Send sub-questions, because there is no limit, you can pack them in bulk, then sort them directly according to the largest unit value, and then pack them from large to small

10. Blue peptide subsequence (DP, longest common subsequence)

 

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)


s1=input()+'!'
s2=input()+'!'

# 拆分字符串
temp=''
ss1=[]
ss2=[]
for i in range(len(s1)):
   temp+=s1[i]
   if s1[i+1]=='!':
      ss1.append(temp)
      temp=''
      break
   if s1[i+1].isupper():
      ss1.append(temp)
      temp=''

for i in range(len(s2)):
   temp+=s2[i]
   if s2[i+1]=='!':
      ss2.append(temp)
      break
   if s2[i+1].isupper():
      ss2.append(temp)
      temp=''
      
# 处理公共最长字符串
ss1=[0]+ss1
ss2=[0]+ss2
dp = [[0]*1010 for i in range(1010)]
for i in range(1,len(ss1)):
   for j in range(1,len(ss2)):
      dp[i][j]=max(dp[i-1][j],dp[i][j-1])
      if ss1[i]==ss2[j]:
         dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1)

print(dp[len(ss1)-1][len(ss2)-1])
         

Investigating the longest common subsequence, the difficulty here is that it needs to be split. Here, I add terminators to the input to facilitate processing. It is necessary to keep in mind the longest common self-sequence template

dp[i][j] = max( dp[i-1][j] ,dp[i][j-1] )

if s1=s2:
        dp=max( dp[i][j] , dp[i-1][j-1]+1 )

11. Chorus formation (longest increasing subsequence)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)


# 两次连续最长递增字符列
n=int(input())
rem = [0]+list(map(int,input().split()))  # 处理下标
dp1=[1]*(n+1)  # 从左到右
dp2=[1]*(n+1)  # 从右到左

for i in range(2,n+1):  # 顺序找最长公共子序列
   for j in range(1,i):
      if rem[j]<rem[i]:
         dp1[i]=max(dp1[i],dp1[j]+1)
#print(*dp1)
for i in range(n-1,-1,-1):  # 逆序找最长公共子序列
   for j in range(n,i,-1):
      if rem[j]<rem[i]:
         dp2[i]=max(dp2[i],dp2[j]+1)
#print(*dp2)
         
ans=0
for i in range(1,n+1):  # 计算最大值
   ans=max(dp1[i]+dp2[i]-1,ans)
  # print(ans)
print(n-ans)

Remember that the most increasing subsequence starts from 1, and the initial dp is all 1, because it is one, and then pay attention to the recursive formula of the longest increasing subsequence.

12. String edit distance (DP, classic problem DP)

 

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)




def init(s,t):

    dp = [[0 for i in range(len(t) + 1)] for j in range(len(s) + 1)]
    for i in range(len(s) + 1):
        dp[i][0] = 0

    for j in range(1,len(t) + 1):
        dp[0][j] = 999999

    return dp

if __name__ == '__main__':
    s = list(input())
    t = list(input())

    dp=init(s,t)

    for i in range(len(s)):
        for j in range(len(t)):
            if s[i] == t[j]:
                dp[i + 1][j + 1] = dp[i][j]
            else:
                dp[i + 1][j + 1] = min(dp[i][j] + 1, dp[i][j + 1])

    print(dp[-1][-1])

The dynamic programming of edit distance is not very good, this needs more practice
 

TemplatePython



def init(s,t):

    dp = [[0 for i in range(len(t) + 1)] for j in range(len(s) + 1)]
    for i in range(len(s) + 1):
        dp[i][0] = 0

    for j in range(1,len(t) + 1):
        dp[0][j] = 999999

    return dp

if __name__ == '__main__':
    s = list(input())
    t = list(input())

    dp=init(s,t)

    for i in range(len(s)):
        for j in range(len(t)):
            if s[i] == t[j]:
                dp[i + 1][j + 1] = dp[i][j]
            else:
                dp[i + 1][j + 1] = min(dp[i][j] + 1, dp[i][j + 1])
                dp[i + 1][j + 1] = min( dp[i + 1][j + 1] ,dp[j+1][i]+1)

    print(dp[-1][-1])

Template C++

#include<iostream>
#include<algorithm>
#include<set>
#include<string>

using namespace std;
#define INF 99999999
string s, t;
int dp[1010][1010];

void init(){
    for (int i = 0; i <= s.size(); i++) dp[i][0] = 0;
    for (int j = 1; j <= t.size(); j++) dp[0][j] = INF;
}

int main() {
    cin >> s >> t;
    
    init();
    
    for (int i = 1; i <= s.size(); i++) {
        for (int j = 1; j <= t.size(); j++) {
            if (s[i - 1] == t[j - 1]) dp[i][j] = dp[i - 1][j - 1];
            else  
                dp[i][j] = min(dp[i - 1][j - 1],min(dp[i - 1][j], dp[i][j - 1])) + 1;
        }
    }
    cout << dp[s.size()][t.size()];
    return 0;
}

13. Xiaoming's knapsack 1 (classic 0/1 knapsack problem DP)

 

def solve(N,C):  # 从左到右,从上到下 (先种类,再体积)
    for i in range(1,N+1): # N种物品,先1种,再2种......
        for j in range(1,C+1):  # 当前背包体积
            if c[i]>j : dp[i][j] = dp[i-1][j]    # 新增的第i种物品的体积大于背包重量,只有不选,继承上一个选择
            else: dp[i][j] = max(dp[i-1][j-c[i]]+w[i],dp[i-1][j])  # 装或者不装,找最大值
            
    return dp[N][C]
N,C= map(int,input().split())
n=3010
dp = [[0]*n for i in range(n)]  # 初始化dp数组,预留更大空间
c=[0]*n  # 记录体积
w=[0]*n # 记录价值
for i in range(1,N+1):   #读入N种物品的价值和体积
    c[i],w[i] = map(int,input().split())
print(solve(N,C))

14. Longest common subsequence (template question)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

n,m=map(int,input().split())
a=[0]+list(map(int,input().split()))
b=[0]+list(map(int,input().split()))
dp=[[0]*1010 for i in range(1010)]
for i in range(1,n+1):
   for j in range(1,m+1):
      dp[i][j]=max(dp[i-1][j],dp[i][j-1])
      if a[i]==b[j]:
         dp[i][j]=max(dp[i][j],dp[i-1][j-1]+1)
print(dp[n][m])

 Longest common subsequence, template question, note that it is enough to initialize the dp array to 0.

15. The longest continuous increasing subsequence (DP template)

import sys  #设置递归深度
import collections  #队列
import itertools  # 排列组合
import heapq  #小顶堆
import math
sys.setrecursionlimit(300000)

n=int(input())
save=[0]+list(map(int,input().split()))
dp=[1]*(n+1)  # 注意初始化从1开始
for i in range(2,n+1):
   for j in range(1,i):
      if save[i]>save[j]:
         dp[i]=max(dp[i],dp[j]+1)
print(max(dp))   #最长公共子序列,dp[n]不一定是最大的

#a : 1 4 5 2 1
#DP: 1 2 3 2 1

Misunderstanding: dp[ n ] is not necessarily the largest , you must pay attention to the misunderstanding, and now you find that dp[ i ] is the maximum value of the subsequence whose tail element is i.

Guess you like

Origin blog.csdn.net/weixin_52261094/article/details/129882917