关于错位排序

先引用一下wuyiqi的话
bywyq

警示他人和自己

现在开始讲错排

其实错排的递推式大家应该都是知道的: d p [ i ] = ( i 1 ) ( d p [ i 1 ] + d p [ i 2 ] )
然而有多少人知道原理呢?
以前我也以为知道原理并没有什么用
知道做到一道,练一篇蛮好的题解(来自mengxiang000000)都看不懂

于是就去补了一下原理,下面是本人的理解
对于 d p [ i ] ,我们可以由前面的dp转移过来(动态规划的本质就是转移嘛)
我们考虑把第i个放到第k个位置 ( 1 <= k < i ) ,那第k个又要放哪里呢?
1.k放到第i个的位置则就是把i和k对调了一下,所以就是(i-2)个数进行错排,方案有 d p [ i 2 ]
2.k放到除了i和k的(n-1)个位置上(这种我也看了好久)这里讲一下自己的理解
这里写图片描述
把i先放在k的地方,然后删除k,把位置i放到位置k的地方,因为数值k不能放到位置i上,所以就第i位的限制条件就相当于相当于第k位,于是就能推出有 d p [ i 1 ] 种方案

最后考虑k可以选取 1 i 1 所以就可以推出转移方程 d p [ i ] = ( i 1 ) ( d p [ i 1 ] + d p [ i 2 ] )
Is it clear?

于是弄懂错排的原理之后,再回过头去做这道
发现只需要改变一点点的细节,就可以马上A掉,下面给出核心代码

for (LL i = 2; i <= cnt; ++i)
    d[0] = d[0] * i;
d[1] = d[0] * cnt;
for (LL i = 2; i <= all - cnt; ++i)
    d[i] = (i - 1) * (d[i - 1] + d[i - 2]) + cnt * d[i - 1];

猜你喜欢

转载自blog.csdn.net/jokingcoder/article/details/81253999