题目
难度:※※※※
学习点:
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)
题目
难度:※※
学习点:
因为我是提前看到了题目的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])
题目
难度:※※※※※
学习点:
一个作弊点:基本上N是什么,就遍历什么
这里N是列,所以就遍历列
每一列有四种情况,蓝蓝,蓝白,白蓝和白白,因为出现白白机器人无法走到右下角,因此排除这种情况
我们统计每一列这三种情况下满足题目要求的规划方案,用a,b,c分别表示
先可以得出a b c的迭代公式;
然后发现b和c之间的关系;
然后我们要计算的是最后一列的情况也就是a+b,发现等于下一轮的c,经过一些替换后就得到了一个关于c的线性非齐次递推关系
用数值分析里面学过的方法来计算c即可
这里面有幂和除法取模,所以还用到了快速幂和费马小定理(虽然测试用例不用快速幂也可以通过)
这题非常非常非常难,每一步都很难,而且没学过数值分析求解递推关系的话,这题可能根本不会做
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)
题目
难度:※
学习点:
我的公式已经算出来了,但是我的思维局限在了计算公式的导数,然后找到最小值周围的k点
但其实用程序来说,k的情况是固定的,所以直接去遍历然后找最小值即可
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 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
难度:※
学习点:
把情况考虑清楚就行
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)
链接
难度:※※
学习点:
如何输出保留两位小数的浮点数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}')