T4解法

概念:

  1. 可见山,不可见山:字面意思。
  2. 块:两个可见山之间的部分。参考下图:

  1. $inv_x$:$x$ 的逆元。

前置芝士:

  1. 逆元

只需知道 $\dfrac a b\bmod P=(a\bmod P)×(inv_b\bmod P)\bmod P$ 即可。

  1. 求积公式

为了方便表达,$∏\limits_{i=1}^na_i$ 表示 $a_1×a_2×…×a_n$ (类比 $∑$ 理解)。

思路:

根据题意可知,可见山是最高的 $l+r-1$ 座山。

去掉其中最高的山,还剩 $l+r-2$ 座山。

我们只需在这 $l+r-2$ 座山中:

  1. 选取 $l-1$ 座,升序排在最高的山左边
  2. 剩下 $r-1$ 座,降序排在最高的山右边
  3. 还剩 $n-l-r+2$ 座不可见山,插在可见山形成的块里

就可以满足题意。

我们分别考虑前两步和第三步对总方案数的影响:

前两步:从 $l+r-2$ 中选 $l-1$ 个,

方案数很明显是:$$ \begin{aligned} &C_{l+r-2}^{l-1} \bmod P\\ =&\dfrac{(l+r-2)!}{(l-1)![(l+r-2)-(l-1)]!}\bmod P\\ =&\dfrac{(l+r-2)!}{(l-1)!(r-1)!}\bmod P\\ =&(l+r-2)!\bmod P×inv_{(l-1)!}\bmod P×inv_{(r-1)!}\bmod P \end{aligned} $$

( $\bmod$ 优先级视为与乘法相同)

当然,我们不太可能把逆元算到 $100!$ 的数量级,所以:$$ \begin{aligned} &\dfrac{(l+r-2)!}{(l-1)!(r-1)!}\bmod P\\ =&(l+r-2)!÷1÷2…÷(l-1)÷1÷2…÷(r-1)\bmod P\\ =&(l+r-2)!×∏\limits_{i=1}^{l-1}\dfrac 1i×∏\limits_{i=1}^{r-1}\dfrac 1i\bmod P\\ =&(l+r-2)!\bmod P×∏\limits_{i=1}^{l-1}inv_i\bmod P×∏\limits_{i=1}^{r-1}inv_i\bmod P \end{aligned} $$ 别看上面的公式长得吓人,特别好理解

所以我们可以提前预处理出 $1$ 到 $min(l-1,r-1)$ 的逆元:

for(int i = 2;i <= max(l, r) - 1;++i)
    inv[i] = (P - (P / i)) * inv[P % i] % P;

然后令 $inv_x=$ 原来的 $∏\limits_{i=1}^{x}inv_i$,也就是把 $inv$ 变成一个“前缀积”数组:

for(int i = 2;i <= max(l, r) - 1;++i)
    inv[i] = inv[i - 1] * inv[i] % P;

这样,原式就变为了:

$(l+r-2)!\bmod P×inv_{l-1}\bmod P×inv_{r-1}\bmod P$,简单了很多。

当然这个“前缀积”优化可加可不加。

第三步:不可见山的方案

我们设 $f[i][j]$ 表示有 $i$ 座山,$j$ 个块时的不可见山插入方案数。

根据题意可知,有 $l+r-2$ 个块,那么我们只需要递推得到 $f[n][l+r-2]$ 即可。

现在我们来推式子:


首先,$i$ 座山一定是由 $i-1$ 座山 $+1$ 座山得来的,

即 $f[i][j]$ 是由 $f[i-1][…]$ 转移而来的。

我们需要讨论 $+$ 的那一座山插在哪:

(下面的图中,黑色代表转移前的 $i-1$ 座山,红色代表新来的一座山)

(假设山是从小到大依次插入的,顺序不会影响总方案数)


第一种情况:插在两边

由图可知,原有 $j-1$ 个块,$i-1$ 个点,即转移前状态为 $f[i-1][j-1]$。

(插到最左边同理)

另外需要注意,转移时不需要分类讨论插到最左边和最右边的情况。

因为两边的差别实际上是可见山的差别,对于不可见山这两种方案是一样的。

而且,$f[i][j]$ 表示的是不可见山的方案数。

所以 $f[i][j]$ 是由 $f[i-1][j-1]$ 这一种状态转移而来的,并非左右两种。

第二种情况:插在中间

由图可知,插入前有 $j$ 个块,转移前状态 $f[i-1][j]$。

但是这个新来的山可以插在中间的任何位置。

原有 $i-1$ 座山,有 $i-2$ 个空(并非块)可以插入。

所以这个状态转移时要 $×(i-2)$。

我们就得到方程:

$$ f[i][j]=(f[i-1][j]×(i-2)+f[i-1][j-1]) \bmod P $$

容易想到,每种可见山的方案都有多种不可见山插入方案,

所以答案应为可见山方案$×$不可见山方案,

即 $f[n][l+r-2]×(l+r-2)!\bmod P×inv_{l-1}\bmod P×inv_{r-1}\bmod P$。

终于没了。思路这么清晰还要什么代码?

#include <iostream>
#define int long long
#define P 1000000007
using namespace std;
int fac[150], inv[150], f[50050][250], n, l, r, ans;
signed main()
{
    inv[0] = inv[1] = fac[1] = 1;f[1][0] = 1;
    cin >> n >> l >> r;
    for(int i = 2;i <= max(l, r) - 1;++i)
        inv[i] = (P - (P / i)) * inv[P % i] % P;
    for(int i = 2;i <= max(l, r) - 1;++i)
        inv[i] = inv[i - 1] * inv[i] % P;
    for(int i = 2;i <= l + r - 2;++i)
        fac[i] = fac[i - 1] * i % P;
    for(int i = 1;i <= n;++i)
        for(int j = 1;j <= l + r - 2;++j)
            f[i][j] = (f[i - 1][j] * (i - 2) + f[i - 1][j - 1]) % P;
    cout << f[n][l + r - 2] * fac[l + r - 2] % P * inv[l - 1] % P * inv[r - 1] % P;
    return 0;
}
posted @ 2021-10-11 21:06  5k_sync_closer  阅读(1)  评论(0编辑  收藏  举报  来源