列表

详情


100146. 统计感冒序列的数目

给你一个整数 n 和一个下标从 0 开始的整数数组 sick ,数组按 升序 排序。

有 n 位小朋友站成一排,按顺序编号为 0 到 n - 1 。数组 sick 包含一开始得了感冒的小朋友的位置。如果位置为 i 的小朋友得了感冒,他会传染给下标为 i - 1 或者 i + 1 的小朋友,前提 是被传染的小朋友存在且还没有得感冒。每一秒中, 至多一位 还没感冒的小朋友会被传染。

经过有限的秒数后,队列中所有小朋友都会感冒。感冒序列 指的是 所有 一开始没有感冒的小朋友最后得感冒的顺序序列。请你返回所有感冒序列的数目。

由于答案可能很大,请你将答案对 109 + 7 取余后返回。

注意,感冒序列 包含一开始就得了感冒的小朋友的下标。

 

示例 1:

输入:n = 5, sick = [0,4]
输出:4
解释:一开始,下标为 1 ,2 和 3 的小朋友没有感冒。总共有 4 个可能的感冒序列:
- 一开始,下标为 1 和 3 的小朋友可以被传染,因为他们分别挨着有感冒的小朋友 0 和 4 ,令下标为 1 的小朋友先被传染。
然后,下标为 2 的小朋友挨着感冒的小朋友 1 ,下标为 3 的小朋友挨着感冒的小朋友 4 ,两位小朋友都可以被传染,令下标为 2 的小朋友被传染。
最后,下标为 3 的小朋友被传染,因为他挨着感冒的小朋友 2 和 4 ,感冒序列为 [1,2,3] 。
- 一开始,下标为 1 和 3 的小朋友可以被传染,因为他们分别挨着感冒的小朋友 0 和 4 ,令下标为 1 的小朋友先被传染。
然后,下标为 2 的小朋友挨着感冒的小朋友 1 ,下标为 3 的小朋友挨着感冒的小朋友 4 ,两位小朋友都可以被传染,令下标为 3 的小朋友被传染。
最后,下标为 2 的小朋友被传染,因为他挨着感冒的小朋友 1 和 3 ,感冒序列为  [1,3,2] 。
- 感冒序列 [3,1,2] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] 。
- 感冒序列 [3,2,1] ,被传染的顺序:[0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] => [0,1,2,3,4] 。

示例 2:

输入:n = 4, sick = [1]
输出:3
解释:一开始,下标为 0 ,2 和 3 的小朋友没有感冒。总共有 3 个可能的感冒序列:
- 感冒序列 [0,2,3] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3] 。
- 感冒序列 [2,0,3] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3] 。
- 感冒序列 [2,3,0] ,被传染的顺序:[0,1,2,3] => [0,1,2,3] => [0,1,2,3] => [0,1,2,3] 。

 

提示:

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
class Solution { public: int numberOfSequence(int n, vector<int>& sick) { } };

python3 解法, 执行用时: 120 ms, 内存消耗: 24 MB, 提交时间: 2023-12-03 22:51:40

MOD = 1_000_000_007
MX = 100_000

# 组合数模板
fac = [0] * MX
fac[0] = 1
for i in range(1, MX):
    fac[i] = fac[i - 1] * i % MOD

inv_fac = [0] * MX
inv_fac[MX - 1] = pow(fac[MX - 1], -1, MOD)
for i in range(MX - 1, 0, -1):
    inv_fac[i - 1] = inv_fac[i] * i % MOD

def comb(n: int, k: int) -> int:
    return fac[n] * inv_fac[k] % MOD * inv_fac[n - k] % MOD

class Solution:
    def numberOfSequence(self, n: int, a: List[int]) -> int:
        m = len(a)
        total = n - m
        ans = comb(total, a[0]) * comb(total - a[0], n - a[-1] - 1) % MOD
        total -= a[0] + n - a[-1] - 1
        e = 0
        for p, q in pairwise(a):
            k = q - p - 1
            if k:
                e += k - 1
                ans = ans * comb(total, k) % MOD
                total -= k
        return ans * pow(2, e, MOD) % MOD

java 解法, 执行用时: 24 ms, 内存消耗: 44.4 MB, 提交时间: 2023-12-03 22:51:54

class Solution {
    private static final int MOD = 1_000_000_007;
    private static final int MX = 100_000;

    // 组合数模板
    private static final long[] FAC = new long[MX];
    private static final long[] INV_FAC = new long[MX];

    static {
        FAC[0] = 1;
        for (int i = 1; i < MX; i++) {
            FAC[i] = FAC[i - 1] * i % MOD;
        }
        INV_FAC[MX - 1] = pow(FAC[MX - 1], MOD - 2);
        for (int i = MX - 1; i > 0; i--) {
            INV_FAC[i - 1] = INV_FAC[i] * i % MOD;
        }
    }

    private static long comb(int n, int k) {
        return FAC[n] * INV_FAC[k] % MOD * INV_FAC[n - k] % MOD;
    }

    public int numberOfSequence(int n, int[] a) {
        int m = a.length;
        int total = n - m;
        long ans = comb(total, a[0]) * comb(total - a[0], n - a[m - 1] - 1) % MOD;
        total -= a[0] + n - a[m - 1] - 1;
        int e = 0;
        for (int i = 1; i < m; i++) {
            int k = a[i] - a[i - 1] - 1;
            if (k > 0) {
                e += k - 1;
                ans = ans * comb(total, k) % MOD;
                total -= k;
            }
        }
        return (int) (ans * pow(2, e) % MOD);
    }

    private static long pow(long x, int n) {
        long res = 1;
        for (; n > 0; n /= 2) {
            if (n % 2 > 0) {
                res = res * x % MOD;
            }
            x = x * x % MOD;
        }
        return res;
    }
}

cpp 解法, 执行用时: 16 ms, 内存消耗: 34 MB, 提交时间: 2023-12-03 22:52:09

const int MOD = 1'000'000'007;
const int MX = 100'000;

long long q_pow(long long x, int n) {
    long long res = 1;
    for (; n > 0; n /= 2) {
        if (n % 2) {
            res = res * x % MOD;
        }
        x = x * x % MOD;
    }
    return res;
}

// 组合数模板
long long fac[MX], inv_fac[MX];

auto init = [] {
    fac[0] = 1;
    for (int i = 1; i < MX; i++) {
        fac[i] = fac[i - 1] * i % MOD;
    }
    inv_fac[MX - 1] = q_pow(fac[MX - 1], MOD - 2);
    for (int i = MX - 1; i > 0; i--) {
        inv_fac[i - 1] = inv_fac[i] * i % MOD;
    }
    return 0;
}();

long long comb(int n, int k) {
    return fac[n] * inv_fac[k] % MOD * inv_fac[n - k] % MOD;
}

class Solution {
public:
    int numberOfSequence(int n, vector<int> &a) {
        int m = a.size();
        int total = n - m;
        long long ans = comb(total, a[0]) * comb(total - a[0], n - a.back() - 1) % MOD;
        total -= a[0] + n - a.back() - 1;
        int e = 0;
        for (int i = 0; i < m - 1; i++) {
            int k = a[i + 1] - a[i] - 1;
            if (k) {
                e += k - 1;
                ans = ans * comb(total, k) % MOD;
                total -= k;
            }
        }
        return ans * q_pow(2, e) % MOD;
    }
};

golang 解法, 执行用时: 16 ms, 内存消耗: 7.6 MB, 提交时间: 2023-12-03 22:52:35

// 组合数模板
const mod = 1_000_000_007
const mx = 100_000

var fac, invFac [mx]int

func init() {
	fac[0] = 1
	for i := 1; i < mx; i++ {
		fac[i] = fac[i-1] * i % mod
	}
	invFac[mx-1] = pow(fac[mx-1], mod-2)
	for i := mx - 1; i > 0; i-- {
		invFac[i-1] = invFac[i] * i % mod
	}
}

func comb(n, k int) int {
	return fac[n] * invFac[k] % mod * invFac[n-k] % mod
}

func numberOfSequence(n int, a []int) int {
	m := len(a)
	total := n - m
	ans := comb(total, a[0]) * comb(total-a[0], n-a[m-1]-1) % mod
	total -= a[0] + n - a[m-1] - 1
	e := 0
	for i := 1; i < m; i++ {
		k := a[i] - a[i-1] - 1
		if k > 0 {
			e += k - 1
			ans = ans * comb(total, k) % mod
			total -= k
		}
	}
	return ans * pow(2, e) % mod
}

func pow(x, n int) (res int) {
	res = 1
	for ; n > 0; n /= 2 {
		if n%2 > 0 {
			res = res * x % mod
		}
		x = x * x % mod
	}
	return
}

上一题