LC 2954. 统计感冒序列的数目
https://leetcode.cn/problems/count-the-number-of-infection-sequences/description/
这题初看还有点难,但是细看是个比较简单的组合问题,可能唯一麻烦一点的就是需要求解一下乘法逆元,不过好在我有模板。
sick之间分为两种情况处理:
- 中间的sick, 假设两者中间有N个人,那么有2^(n-1)中排列可能。
- 而两边的sick, 即使中间有N个人,那么只有1种排列可能。
接着就是把多个区间的人开始做排列组合,假设有4个区间分别是a,b,c,d的话,那么排列组合的可能性是
\[A(a+b+c+d) / A(a) / A(b) / A(c) / A(d)\] 所有人之间假设可以任意排列,但是a,b,c,d内部不能任意排列,其中 \(A(x) = x!\)
#!/usr/bin/env python # coding:utf-8 # Copyright (C) dirlt from typing import List # 费马小定理, 但是这里必须确保MOD是质数 # b^MOD % MOD = b # b^(MOD-1) % MOD = 1 # b^(MOD-2) % MOD = (b^-1) % MOD def pow_mod(a, b, MOD): res = 1 while b: if b & 0x1: res = (res * a) % MOD a = (a * a) % MOD b = b >> 1 return res def div_mod(b, MOD): return pow_mod(b, MOD - 2, MOD) def fac_mod(n, MOD): res = 1 for i in range(1, n + 1): res = (res * i) % MOD return res class Solution: def numberOfSequence(self, n: int, sick: List[int]) -> int: MOD = 10 ** 9 + 7 gap = [] middle = [] for i in range(1, len(sick)): g = sick[i] - sick[i - 1] - 1 if g > 0: middle.append(g) gap.append(g) if sick[0] != 0: gap.append(sick[0]) if sick[-1] != n - 1: gap.append(n - 1 - sick[-1]) # print(gap, middle) ans = 1 for x in middle: ans *= pow_mod(2, x - 1, MOD) ans %= MOD ans *= fac_mod(sum(gap), MOD) ans %= MOD for g in gap: r = fac_mod(g, MOD) ans *= div_mod(r, MOD) ans %= MOD return ans