AtCoder ABC132

陷入了“会做,但不完全会做”的状况
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()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值