先手选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])