其他分享
首页 > 其他分享> > ARC138E Decreasing Subsequence

ARC138E Decreasing Subsequence

作者:互联网

\(\texttt{或许更好的阅读体验}\)

\(\texttt{link}\)

第一步是巧妙的转化:对于 \(a_i>0\),连边 \((i,a_i-1)\)。

对于每个序列 \(a\),连边后形成若干条链

假设选出的 \(k\) 个点为 \(b_1,b_2,...,b_k\),并且 \(b_1<b_2<...<b_k\),对应的 \(a_{b_1}-1,...,a_{b_k}-1\) 为了方便记作 \(c_1,c_2,...,c_k\),则有:

\[c_k<c_{k-1}<...<c_1<b_1<b_2<...<b_k \]

这可以由 \(b_1>c_1\),\(c\) 递减,\(b\) 递增推导出来。

也就是说,在 \(a\) 确定的前提下,在 \([0,n]\) 中选出 \(2k\) 个点,它们对应的子序列有且仅有一种

考虑枚举前 \(k\) 个点以及所在链上的其他点的个数 \(i\),后 \(k\) 个点以及所在链上的其他点的个数 \(j\),则方案数为:

\[\dbinom{n+1}{i+j}\begin{Bmatrix}i\\k\end{Bmatrix}\begin{Bmatrix}j\\k\end{Bmatrix}\sum\limits_{x=1}^{n+1-i-j}\begin{Bmatrix}n+1-i-j\\x\end{Bmatrix} \]

将 \(i\) 个点分成 \(j\) 条链的方案数等价于第二类斯特林数,因为链上总是由编号大的指向编号小的。

注意一下实现做个前缀和就可以做到 \(\mathrm{O(n^2)}\)。

\(\texttt{Code:}\)

#include <bits/stdc++.h>
using namespace std;
const int cmd = 1e9 + 7;
inline int add(int a, int b) {a += b; return a < cmd ? a : a - cmd;}
inline int sub(int a, int b) {a -= b; return a < 0 ? a + cmd : a;}
inline int mul(int a, int b) {return 1ll * a * b % cmd;}
int fpow(int a, int b) {
    int res = 1;
    for (; b; b >>= 1, a = mul(a, a))
        if (b & 1) res = mul(res, a);
    return res;
}
const int maxn = 5e3 + 5;
int n, k, S2[maxn][maxn], fac[maxn], ifac[maxn];
int C(int n, int m) {return mul(fac[n], mul(ifac[m], ifac[n - m]));}
int main() {
    scanf("%d%d", &n, &k);
    S2[1][1] = 1;
    for (int i = 2; i <= n + 1; i++)
    for (int j = 1; j <= i; j++)
        S2[i][j] = add(S2[i - 1][j - 1], mul(S2[i - 1][j], j));
    fac[0] = ifac[0] = 1;
    for (int i = 1; i <= n + 1; i++) {
        fac[i] = mul(fac[i - 1], i);
        ifac[i] = fpow(fac[i], cmd - 2);
    }
    int ans = 0;
    for (int i = k + k; i <= n + 1; i++) {
        int s1 = 0, s2 = 0;
        for (int j = k; j <= i - k; j++)
            s1 = add(s1, mul(S2[j][k], S2[i - j][k]));
        if (i < n + 1) {
            for (int j = 1; j <= n + 1 - i; j++)
                s2 = add(s2, S2[n + 1 - i][j]);
        } else s2 = 1;
        ans = add(ans, mul(s1, mul(s2, C(n + 1, i))));
    }
    printf("%d", ans);
    return 0;
}

标签:return,int,cmd,Subsequence,maxn,Bmatrix,Decreasing,mul,ARC138E
来源: https://www.cnblogs.com/klii/p/16128517.html