22.4.26T4题解

从dp到容斥

Posted by tofucurd on April 26, 2022

题意

求一个长度为$N$且恰好有$M$个逆序对的排列个数。

题解

step 0

容易有一个$O(N^2)$的$dp$:定义$dp_{i,j}$表示前$i$有$j$个逆序对。

转移时只需要关注这一个对前$i-1$做的贡献即可:$dp_{i,j}=\sum_{k=j-i+1}^{j} {dp_{i-1,k}}$

step 1

观察$O(N^2 \times M) \ dp$方程:$dp_{i,j}=\sum_{k=j-i+1}^{j} {dp_{i-1,k}}$

每一步本质上是在为第$i$个数从$[i,0)$中选一个贡献为$k$的值

所以原问题可以转化为:

有方程:$(\sum_{i=1}^{n} {x_i})=m$,$x_i \in [0,i)$,求其解的个数.

step 2

因为$x_i \in [0,i)$比较恶心,所以先考虑$x_i \in [0,+\infty)$的情况,再减去不合法的,即${x}$中有一些$A={x_i|x_i \ge i} \subset S=[1,n]$,于是使用容斥,有:

\[\text{ans}=\sum_{A \in S} {(-1)^{|A|}\times f(A)}\]

$f(A)$为集合$A$的贡献(方案数)。

现在求$f(A)$:

子问题

有方程:$(\sum_{i=1}^{n} {x_i})=m$,$x_i \in [0,+ \infty)$,求其解的个数.

考虑使用插板法,即把$m$拆成$m$个$1$,再插$n-1$个板进去(注意可以插同一个空),所以有:

\[\text{ans}=C_{m+n-1}^{n-1}\]
原问题

有方程:$(\sum_{i=1}^{n} {x_i})=m$,$x_i \in [lim_i,+ \infty)$,求其解的个数.

可以先把每个$x_i$减去$lim_i$,就变成了子问题,只不过$m$变为了$m-\sum_{i=1}^{n} {lim_i}$,所以有:

\[\text{ans}=C_{m-(\sum{lim_i})+n-1}^{n-1}\]

所以有: \(f(A)=C_{m-(\sum{A_i})+n-1}^{n-1}\)

于是:

\[\text{ans}=\sum_{A \in S} {(-1)^{|A|}\times C_{m-(\sum{A_i})+n-1}^{n-1}}\]

step 3

考虑优化,可以发现$A$的贡献只与|A|和$\sum{A_i}$有关,所以我们定义$dp_{i,j}$表示$|A|=i$且$\sum{A_i}=j$的$A$的数量,于是:

\[\text{ans}=\sum_{i=0}^{n} {\sum_{j=i\times(i+1)/2}^{m} {((-1)^{i}\times C_{m-j+n-1}^{n-1}}\times dp_{i,j})}\]

因为$j \in [i\times(i+1)/2,m]$,所以实际上平均下来$j$只有$O(\sqrt{m})$个,所以统计答案是$O(n\sqrt{m})$的。

step 4

考虑求$dp_{i,j}$,因为集合无序,所以我们钦定$A$中的元素降序排序后形成数组$a$,考虑对$a$进行$dp$,将新的$a_i$分成$=1$与$\ne 1$考虑,有:

\[dp_{i,j}=dp_{i-1,j-i}+dp_{i,j-i}\]

又因有$a_i \le n$,所以要减去超过$n$的情况,这时只可能出现一个$n+1$的情况,所以再减去这种情况即可:

\[dp_{i,j}=dp_{i-1,j-i}+dp_{i,j-i}-dp_{i-1,j-n-1}\]

时间复杂度$O(n\sqrt{m})$

step 5

由于卡空间,所以使用滚动数组优化,边$dp$边统计答案即可。

总时间复杂度$O(n+m+n\sqrt{m})$,空间复杂度$O(n+m)$。