关于错位排序

本文深入讲解了错排问题及其递推式的原理,通过详细的步骤解释了如何从问题本质出发,推导出动态规划的转移方程,并给出了核心代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

先引用一下wuyiqi的话
bywyq

警示他人和自己

现在开始讲错排

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

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

最后考虑k可以选取 1 1 i1所以就可以推出转移方程 dp[i]=(i1)(dp[i1]+dp[i2]) 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];
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值