陷入了“会做,但不完全会做”的状况
C
水题,排序找中间数两边的差值
D
组合数学
求把n个相同的球分到m个相同的盒子,1每个盒子至少一个球2每个盒子球不限的组合数
空挡插隔板法,高中数学
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @author : yhdu@tongwoo.cn
# @desc :
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
mod = 10 ** 9 + 7
def pw(a, x):
if x == 0:
return 1
temp = pw(a, x >> 1)
if x & 1:
return temp * temp * a % mod
else:
return temp * temp % mod
def inv(x):
return pw(x, mod - 2)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n, k = map(int, fp.readline().split())
R, B = n - k, k
def cmb(x, y):
if x < y:
return 0
return fac[x] * inv(fac[y]) * inv(fac[x - y]) % mod
fac = [1] * 5005
for i in range(2, 5005):
fac[i] = fac[i - 1] * i % mod
for i in range(1, B + 1):
ans_r = cmb(R + 1, i)
ans = cmb(B - 1, i - 1) * ans_r % mod
print(ans)
if __name__ == "__main__":
main()
E
一开始用dfs去求(3步能访问到的点对),明显TLE
分层图求最短路
原图分为3层,每个点拆成
V
0
,
V
1
,
V
2
V_0,V_1,V_2
V0,V1,V2,
假如
(
u
,
v
)
(u,v)
(u,v)间有一条有向边
把边拆成
(
u
0
,
v
1
)
,
(
u
1
,
v
2
)
,
(
u
2
,
v
3
)
(u_0,v_1),(u_1,v_2),(u_2,v_3)
(u0,v1),(u1,v2),(u2,v3)
走三的倍数步能回到0层,这样只要能走到
T
0
T_0
T0点就有解
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @author : yhdu@tongwoo.cn
# @desc :
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
n, m = map(int, fp.readline().split())
g = [[] for _ in range(n * 3)]
for i in range(m):
u, v = map(int, fp.readline().split())
u, v = u - 1, v - 1
u0, u1, u2 = u, u + n, u + 2 * n
v0, v1, v2 = v, v + n, v + 2 * n
g[u0].append(v1)
g[u1].append(v2)
g[u2].append(v0)
S, T = map(int, fp.readline().split())
S, T = S - 1, T - 1
vis = [-1] * (3 * n)
qu = deque()
qu.append(S)
vis[S] = 0
while qu:
cur = qu.popleft()
if cur == T:
break
for v in g[cur]:
if vis[v] == -1:
vis[v] = vis[cur] + 1
qu.append(v)
if vis[T] == -1:
print(-1)
else:
print(vis[T] // 3)
if __name__ == "__main__":
main()
F
分块
重要的是想清楚每一块代表的数字
# -*- coding: utf-8 -*-
# @time : 2023/6/2 13:30
# @author : yhdu@tongwoo.cn
# @desc :
# @file : atcoder.py
# @software : PyCharm
import bisect
import copy
import sys
from sortedcontainers import SortedList
from collections import defaultdict, Counter, deque
from functools import lru_cache, cmp_to_key
import heapq
import math
sys.setrecursionlimit(100010)
def main():
items = sys.version.split()
if items[0] == '3.10.6':
fp = open("in.txt")
else:
fp = sys.stdin
mod = 10 ** 9 + 7
N, K = map(int, fp.readline().split())
i = 1
g = []
"""
记录[l..r]的区间,每个区间中n//x都相同
如10分为[1,1],[2,2],[3,3],[4,5],[6,10]
记录区间中元素的数量g为[1,1],[2,1],[3,1],[5,2],[10,5] 第一个元素用不到,即为[1,1,1,2,5]
dp时按照这些分块来推算
f[2][4]即为当前长度为2,可以选择[4,5]时的从[1,1]...到[4,5]的总和
f[i][j]可以通过选当前分块 f[i-1][l]+不选当前分块 f[i][j-1]计算而得
观察可以发现l=m+1-j
例如当前分块是[4,5],那么上一次能选到的是[1,1],[2,2] 即为f[i][4] = f[i][3] + f[i-1][2]
"""
while i <= N:
j = N // (N // i) # i: left, r: right
g.append(j - i + 1)
i = j + 1
m = len(g)
g = [0] + g
f = [[1] * (m + 1) for _ in range(K + 1)]
for i in range(1, K + 1):
f[i][0] = 0
for j in range(1, m + 1):
l = m + 1 - j
f[i][j] = (f[i][j - 1] + g[j] * f[i - 1][l]) % mod
print(f[K][m])
if __name__ == "__main__":
main()