蓝桥杯 python 研究生组 备战刷题

动态规划

1. 奖杯排序

题目

难度:※※※※

学习点:
defaultdict的使用可以设置字典的初始值,不用担心key不存在问题;
动态规划的难点是:如何定义dp数组的含义,以及考虑清楚每次的情况。

代码:

from collections import defaultdict

mod=10**9+7

N,K=map(int,input().split())
values=list(map(int,input().split()))

# 统计奖杯值v为结尾时,可能的等差k数列个数
dp=defaultdict(int)
# 不断统计奖杯值v出现的次数
cnt=defaultdict(int)

res=0

# 遍历每一个奖杯
for v in values:
  # v为结尾的等差K数列有两种情况:
  # 1. v前面v-k这个奖杯为结尾,后面再跟上一个v
  # 2. v前面v-k这个奖杯为开头,后面再更上一个v
  new=dp[v-K]+cnt[v-K]
  dp[v]+=new
  dp[v]%=mod
  res+=new
  res%=mod
  cnt[v]+=1

print(res)

2. 舞狮表演

题目

难度:※※

学习点:
因为我是提前看到了题目的tag是动态规划,所以很快就知道怎么做了,考场上可能会相对难一点;
有一个易错点是:同行的只需要判断相邻格子是否奇偶同性即可判断是否可以到达;同列的则需要分当前格子奇偶分别讨论

# 用例数量
t=int(input())
for _ in range(t):
    # 格子大小
    n=int(input())
    gezi=[]
    for _ in range(n):
        gezi.append(list(map(int,input().split())))
    ans=[[-1 for _ in range(n)] for _ in range(n)]
    # 先设置好ans的第一行和第一列
    # ans[i][j]表示走到格子i,j时最少需要消耗的钱币数量,一开始都是-1,表示走不到
    if gezi[0][0]%2==0:
        ans[0][0]=n
    else:
        ans[0][0]=0
    for i in range(1,n):
        # 前一个格子可以到达 且 当前格子和前一个格子的奇偶性一致
        if ans[0][i-1]!=-1 and (gezi[0][i-1]+gezi[0][i])%2==0:
            ans[0][i]=ans[0][i-1]
        else:
            break
    for i in range(1,n):
        # 前一个格子可以到达
        if ans[i-1][0]!=-1:
            # 当前格子是奇数
            if gezi[i][0]%2==1:
                ans[i][0]=ans[i-1][0]
            else:
                # 不一致要塞钱
                ans[i][0] = ans[i - 1][0]+n
        else:
            break
    # 遍历非首行和首列
    for i in range(1,n):
        for j in range(1,n):
            # 来自上方的情况
            if ans[i-1][j]!=-1:
                if gezi[i][j]%2==1:
                    up=ans[i-1][j]
                else:
                    up=ans[i-1][j]+n
            else:
                up=-1
            # 来自左边的情况
            if ans[i][j-1]!=-1 and (gezi[i][j-1]+gezi[i][j])%2==0:
                left=ans[i][j-1]
            else:
                left=-1
            # 找最小值
            if up==-1:
                ans[i][j]=left
            elif left==-1:
                ans[i][j]=up
            else:
                ans[i][j]=min(up,left)
            # 如果当前格子走不到,那这一行后面都走不到了
            if ans[i][j]==-1:
                break
    if ans[n-1][n-1]==-1:
        print('NO!')
    else:
        print(ans[n-1][n-1])

数学思维

1. 铺设地砖

题目

难度:※※※※※

学习点:
一个作弊点:基本上N是什么,就遍历什么
这里N是列,所以就遍历列
每一列有四种情况,蓝蓝,蓝白,白蓝和白白,因为出现白白机器人无法走到右下角,因此排除这种情况
我们统计每一列这三种情况下满足题目要求的规划方案,用a,b,c分别表示
先可以得出a b c的迭代公式;
然后发现b和c之间的关系;
然后我们要计算的是最后一列的情况也就是a+b,发现等于下一轮的c,经过一些替换后就得到了一个关于c的线性非齐次递推关系
用数值分析里面学过的方法来计算c即可
这里面有幂和除法取模,所以还用到了快速幂和费马小定理(虽然测试用例不用快速幂也可以通过)

这题非常非常非常难,每一步都很难,而且没学过数值分析求解递推关系的话,这题可能根本不会做

蓝桥杯 python 研究生组 备战刷题_第1张图片

mod=10**9+7
# 快速幂(包含求模)
def quick_pow(a,b):
    res=1
    while b:
        if b%2:
            res=(res*a)%mod # 关键求模处
        b//=2
        a=(a*a)%mod # 关键求模处(这里没有的话,计算会非常慢)
    return res

T=int(input())
for _ in range(T):
    N=int(input())
    if N%2==0:
        t=-1
    else:
        t=1
    res=(quick_pow(2,N+2)+t-3) % mod
    # 费马小定理
    res=(res*quick_pow(6,mod-2)) % mod
    print(res)

2. 最优分组

题目

难度:※

学习点:
我的公式已经算出来了,但是我的思维局限在了计算公式的导数,然后找到最小值周围的k点
但其实用程序来说,k的情况是固定的,所以直接去遍历然后找最小值即可

公式计算解析:
蓝桥杯 python 研究生组 备战刷题_第2张图片

N=int(input())
p=float(input())

ans=1
num=N
for k in range(2,N+1):
    # k要能被N整除
    if N%k==0:
        # 公式计算出这个k下可能要用到的试剂数量
        y=N*(1-(1-p)**k)+N/k
        if y<num:
            num=y
            ans=k
print(ans)

模拟

1. 分布式队列

难度:※※

学习点:
简单题,但是有两个地方要注意
1 sync时不能盲目增加follow队列的元素个数,要检查此时follow队列是不是因为完全同步结束了
2 while循环输入里面要对输入进行异常捕捉,否则会出现段错误

N = int(input())
new_loc = [0 for _ in range(N)]
while True:
    try:
        operation = input().split()
        op = operation[0]
        if op != 'query':
            id = int(operation[1])
            if op == 'add':
                new_loc[0] += 1
            else:
                if new_loc[id] < new_loc[0]:
                    new_loc[id] += 1
        else:
            print(min(new_loc))
    except:
        break

贪心

1. 食堂

难度:※

学习点:
把情况考虑清楚就行

q=int(input())
for _ in range(q):
    a2,a3,a4,b4,b6=map(int,input().split())
    ans=0
    # 遍历6人桌
    t=b6
    for _ in range(t):
        # 先判断这张桌子是否可以坐满
        if a3>=2:
            ans+=6
            b6-=1
            a3-=2
        elif a2>=1 and a4>=1:
            ans+=6
            b6-=1
            a2-=1
            a4-=1
        elif a2>=3:
            ans+=6
            b6-=1
            a2-=3
        # 再判断坐到5人的情况
        elif a2>=1 and a3>=1:
            ans+=5
            b6-=1
            a2-=1
            a3-=1
        # 下面就是坐到4人的情况,6人桌变成4人桌
        else:
            break
    b4+=b6
    # 下面开始处理四人桌
    t=b4
    for _ in range(t):
        if a4>=1:
            ans+=4
            b4-=1
            a4-=1
        elif a2>=2:
            ans+=4
            b4-=1
            a2-=2
        elif a3>=1:
            ans+=3
            b4-=1
            a3-=1
        elif a2>=1:
            ans+=2
            b4-=1
            a2-=1
        else:
            break
    print(ans)

数据结构

1. 星际旅行

链接

难度:※※

学习点:
如何输出保留两位小数的浮点数print(f'{x:.2f}');
在依赖defaultdict的时候要小心一些坑,比如这里path[x]=0如果忘了会有一些测试用例无法通过;
记得检查一些值为0的情况(边界条件);
这题算是比较典型的最短路径问题,用BFS即可解决。

from collections import defaultdict,deque

n,m,Q=map(int,input().split())

# 构造图
graph=defaultdict(set)
for _ in range(m):
    a,b=map(int,input().split())
    graph[a].add(b)
    graph[b].add(a)

ls_ans=[]
pathes={}

# 处理盲盒
for _ in range(Q):
    x,y=map(int,input().split())

    ans = 0
    # 判断x为起点的情况是否统计过
    if x not in pathes:
        visited=defaultdict(bool)
        path=defaultdict(int)
        # 构建初始队列
        q=deque()
        q.append(x)
        visited[x]=True
        path[x]=0
        # 遍历队列
        while len(q):
            # 处理出队列的数据
            curr=q.popleft()
            # 处理要进队列的数据
            for neigh in graph[curr]:
                if not visited[neigh]:
                    visited[neigh]=True
                    q.append(neigh)
                    path[neigh]=path[curr]+1
        pathes[x]=path

    for v in pathes[x].values():
        if v <= y:
            ans += 1
    ls_ans.append(ans)
if Q==0:
    print(f'{float(0)}:.2f')
else:
    print(f'{sum(ls_ans)/Q:.2f}')

你可能感兴趣的:(蓝桥杯,python,职场和发展)