「JOISC 2020 Day2」遗迹 (dp)
如果我们知道每个高度\(h_i\),如何判断其最后是否留下?
我们从后往前扫,如果\(h_i\)被占了,就减一,直到找到一个没被占的占掉,
如果没有找到,那么说明\(i\)不能被留下。
每个数选两次太复杂了,我们把一个数拆成两个“不同”的数,最后方案除掉\(2^n\),
然后就有一个状压\(dp\),设到了第\(i\)位,位置被占的状态为\(S\)的方案数。
这样得到了一个\(O(n2^n)\)的做法。
想想这个状压的转移,发现大部分都只需要直到前缀\(1\)的个数。
那么我们设\(f[i][j]\)表示到了第\(i\)位,状态前缀\(1\)个数为\(j\)。
1.如果这个位置不留下:
\(f[i][j]=f[i+1][j]*(j-cnt2)\)
其中\(cnt2\)表示之前不留下的个数。
2.如果这个位置留下:
似乎不是很好搞。我们考虑贡献未来计算。
如果这一次位置不能使\(j\)变大,那么我们放到以后去计算。
那么
\(f[i][j]+=f[i+1][j]\)
\(f[i][j+k]+=f[i+1][j]*(^{cnt1-j}_{\ \ \ k-1})*g[k-1]*(k+1)\)
其中\(g[k]\)表示\(k\)个放满\(k\)个位置的方案。
这个可以用一个\(dp\)计算,
设\(h[i][j]\)表示考虑了\(i\)个位置,填满了\(j\)个空的方案,显然\(j\)必须小于等于\(i\)。
有\(h[i][j]=h[i-1][j]+2j*h[i-1][j-1]+j(j-1)*h[i-1][j-2]\),
那么\(g[k]=h[k][k]\)。
然后我们就可以\(O(n^3)\)解决问题了。