状压好题。
题意简述
给出一个 $1$ 至 $n$ 的排列 $a_i$ 。定义一个排列 ${p_i}$ 是合法的,要满足 $p_i\ne a_i$ 。
一个排列 ${p_i}$ 的权值可以这样计算:对于每一个逆序对 $(i,j)$ ($p_i > p_j$) ,贡献为 $(j - i)\times(p_i - p_j)$ ,这个排列的权值即所有逆序对的贡献和。
求每一个合法的排列的权值和。
$case$ 组数据, $case \le 10, n \le 16$ 。
主要思路
首先先把下标和值域都转换成 $[0,n-1]$ 。
这么小的数据范围,猜测复杂度大概是指数级别的。
按照从小到大往排列里放数,这样每个数在放入排列时,必定所有在其后的已经在排列中的数都会对其产生贡献。
考虑集合 $S$ 为放了数的位置,已经放了 $0,1,\dots,|S|-1$ 这些数,此时的合法排列(仅考虑已经放的数)方案。
记合法排列总数为 $t(S)$ ,贡献总和为 $f(S)$ ,位置 $pos$ 上的数在所有合法排列中的总和为 $g(S, pos)$ 。
如何转移?对于一个集合 $S$ ,枚举下一个数即( $|S|$ )放的位置 $x,x\ne a_{|S|}$ 。
设 $T = S\ \cup\ {x}$ ,考虑 $S$ 转移至 $T$ 。
对 $f(T)$ 的贡献为: $f(S) + \sum\limits_{i>x,i\in S}(|S|\times t(S) - g(S,i))\times (i - x)$ 。(枚举与数 $|S|$ 形成逆序对的位置)
对 $t(T)$ 的贡献为: $t(S)$ 。(数 $|S|$ 只有一种放法)
对 $g(T,x)$ 的贡献为: $t(S)\times |S|$ 。
对 $g(T,i)$ 的贡献为: $g(S,i)$ ( $i\ne x$ ) 。
初始状态是 $|S|={k}$ 的状态 ( $0\le k\le n - 1$ ) ,如果 $a_0\ne k$ , $f({k})=0,g({k},k)=0,t({k})=1$ 。
参考代码
然后不知道为什么代码写得特别丑……为了卡常
1 |
|
CometOJ 其实有很多高质量题目,比如状压 dp 就还有「Comet#1C」,「Comet#4F」。等我不咕了一定把「Comet#4F」肝出来。