2017山东一轮集训 [乱做]

Day7 逆序对

题目大意:
\(n, m\le 10^5\) 求长度为 \(n\) 的排列中, 逆序对个数为 \(m\) 的有多少个.

分析:
从大到小决定把每个数插在哪里, 这样能确定每个数对逆序对的贡献
\(i\) 个数可以贡献的范围是 \([0, i-1]\)
写成生成函数, 因为是求单项, 等比数列分子分母分开做, 最后 \(O(n)\) 卷积即可
分母是 \(\frac 1{(1-x)^n}\), 这个就是 \(\sum_{i\ge 0} \binom{i+n-1}{n-1}x^i\)
分子是 \(\prod_{i>1} (1-x^i)\). 一个类似拆分数的dp. 见下述 算法1

算法1: 用不重复的数组成 \(m\)
显然被选的数最多根号个, 据此优化 \(dp\)
\(f[v][s]\) 表示选了 \(v\) 个数, 和为 \(s\) 的方案数. 转移时考虑 \(1\) 选不选, 然后其他数整体减一
\(f[v][s] = f[v][s-v] + f[v-1][s-1-(v-1)]\)
本题中组成的数还有上限 \(n\). 注意到上式如果之前一直是合法的, 那么转移后非法只会是出现 \(n+1\)
\(f[v][s]\) -= \(f[v-1][s-(n+1)]\), 将违法情况一出现就销毁掉即可

算法2: 用可重复的数去组成 \(m\)
我们可以分段 \(dp\), 最后两段卷积起来.
权值比 \(\sqrt m\) 小的分一段, 直接用完全背包
权值比 \(\sqrt m\) 大的分一段, 类似算法1 的做,

扩展:
\(m < n\) 时, 分子在 \(m\) 以内有值的地方就是是五边形数了, 有值的地方只有根号个
因此可以出到 \(m < n \le 10^{12}\), \(\mod \approx 10^6\) 的样子
要做一下 \(lucas\) 定理, 预处理 \(mod\) 以内的阶乘, 复杂度是 \(O(\sqrt m) + O(mod)\)

猜你喜欢

转载自www.cnblogs.com/acha/p/9258797.html