A
先手选n-1个就必胜,只有n=1的时候先手必败
s=input() if len(s)==1: print("yukari") else: print("kou")
B
模拟一下
mod=10**9+7 n=int(input()) a=list(map(int,input().split())) idx=0 res=0 for x in input(): if x=="R": idx+=1 if idx==n: idx-=1 else: idx-=1 if idx==-1: idx+=1 res+=a[idx] res%=mod print(res)
C 贪心
偶数的时候就头尾匹配,奇数的时候就先把最大值摘出来
n=int(input()) a=list(map(int,input().split())) a.sort() x=[] if n%2==1: x.append(a.pop()) x=[] for i in range(n//2): x+=[a[i]*a[-(i+1)]] x.sort() print(x[-1]-x[0])
D dfs
子树返回上来的时候如果子树大小是偶数,就切掉这条边即可
这种思想其实还是很常用的,可以做下下面三题
简单 :lc 2872. 可以被 K 整除连通块的最大数目
每块都可被k整除
中等:lc 2440. 创建价值相同的连通块
上一题的基础上加一个枚举因子
困难:划分树
https://ac.nowcoder.com/acm/contest/28260/E
求把树划分成异或和都为m的块 的方案数
from types import GeneratorType def bootstrap(f, stack=[]): #yield def wrappedfunc(*args, **kwargs): if stack: return f(*args, **kwargs) else: to = f(*args, **kwargs) while True: if type(to) is GeneratorType: stack.append(to) to = next(to) else: stack.pop() if not stack: break to = stack[-1].send(to) return to return wrappedfunc n=int(input()) g=[[] for _ in range(n+1)] for _ in range(n-1): u,v=map(int,input().split()) g[u]+=[v] g[v]+=[u] if n%2==1: print(-1) exit() sz=[1]*(n+1) cnt=[0]*(n+1) @bootstrap def dfs(u,fa): for v in g[u]: if v==fa: continue yield dfs(v,u) sz[u]+=sz[v] cnt[u]+=cnt[v] if sz[v]%2==0: cnt[u]+=1 yield None dfs(1,-1) print(cnt[1])
E 线性dp
dp[i][j]前i个数,长度为j的子序列之和
cnt[i][j]前i个数,长度为j的子序列个数
转移
dp[i][j] = dp[i-1][j] + dp[i-1][j-1] * 10 + int(s[i]) * cnt[i-1][j-1]
cnt[i][j] = cnt[i-1][j] + cnt[i-1][j-1]
直接逆序遍历,原地滚动
mod=10**9+7 n,k=map(int,input().split()) s=input() dp=[0]*(k+1) cnt=[0]*(k+1) cnt[0]=1 for i in s: for j in range(k,0,-1): cnt[j]=(cnt[j]+cnt[j-1])%mod dp[j]+=dp[j-1]*10+int(i)*cnt[j-1] dp[j]%=mod print(dp[k])
F 期望dp
dp[i][j]表示从已经有i个2,j个3的状态,到至少有a个2,b个3的期望投掷次数
(i,j)==(a,b) 时 dp[i][j]=0
i==a,可以列出转移方程
dp[i][j]= 1/3 * dp[i][j] + 1/3 * dp[i][j] + 1/3 * dp[i][j+1] + 1 (三个式子分别表示丢1,2,3,丢1没贡献,丢2我已经有a个2了,也相当于没贡献)
移项得 dp[i][j] = dp[i][j+1] + 3
类似的 j==b时,有 dp[i][j] = dp[i+1][j] +3
其他情况
dp[i][j] = 1/3 * dp[i][j] + 1/3 * dp[i+1][j] + 1/3 * dp[i][j+1] + 1
移项得 dp[i][j] = (dp[i+1][j]+dp[i][j+1]+3)/2
可以做一道类似的题复习一下
https://atcoder.jp/contests/dp/tasks/dp_j
mod=10**9+7 x=int(input()) if x==1: print(0) exit() a=b=0 while x%2==0: x//=2 a+=1 while x%3==0: x//=3 b+=1 if x!=1: print(-1) exit() dp=[[0]*(b+1) for _ in range(a+1)] inv2=pow(2,mod-2,mod) for i in range(a,-1,-1): for j in range(b,-1,-1): if (i,j)==(a,b): dp[i][j]=0 elif i==a: dp[i][j]=(dp[i][j+1]+3)%mod elif j==b: dp[i][j]=(dp[i+1][j]+3)%mod else: dp[i][j]=(dp[i+1][j]+dp[i][j+1]+3)*inv2%mod print(dp[0][0])