错位排列及有关例题

错位排列

对于n的一个排列a1,a2,a3...an。如果所有的ai 不等于 i,那么这个排列称为错位排列

求解方法

考虑递推

i元素时如何进行状态转移?

(一)根据错位排列的定义,第i个元素肯定不会放在自己的位置上,故第i个元素的位置有i1种选择。

(二)对于剩下的i1个元素,选择其中任意一个元素k。此时k的位置有两种选择:

1. 放在第i个元素的位置上,宏观上相当于ik的位置互换了。而剩下的i-2个元素依然要求错位排列。方案数为f[i2]

2. 不放在第i个元素的位置上,则相当于剩下的i1个元素全部进行错位排列。方案数为f[i1]

综上,我们可以得到f[i]=(i1)(f[i1]+f[i2])


 

例题 选新娘

题目大意:一共有N对新婚夫妇,其中有M个新郎找错了新娘,求发生这种情况一共有多少种可能.

M个新郎找错了,意味着有且只有M个人是错排,另外人都刚好恰合。于是先求出f[M],表示长度为M的序列的错排。

然而这样就完了吗?并没有,还要看看是哪M个人。从N个人中选M个,也就是组合数CNM,于是答案就是CNMf[M]

复制代码
/*By QiXingzhi*/
#include <cstdio>
#define  r  read()
#define  Max(a,b)  (((a)>(b)) ? (a) : (b))
#define  Min(a,b)  (((a)<(b)) ? (a) : (b))
using namespace std;
typedef long long ll;
#define int ll
const int N = 100010;
const int M = 1010;
const int INF = 1061109567;
inline int read(){
    int x = 0; int w = 1; register int c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) +(x << 1) + c - '0', c = getchar();
    return x * w;
}
int n,m;
int f[30];
inline int JieCheng(int x){
    int res = 1;
    for(int i = 2; i <= x; ++i) res *= i;
    return res;
}
inline int C(int m, int n){
    return JieCheng(n) / (JieCheng(m) * JieCheng(n-m));
}
#undef int
int main(){
#define int ll
    n = r;
    m = r;
    f[1] = 0;
    f[2] = 1;
    for(int i = 3; i <= m; ++i){
        f[i] = (i - 1) * (f[i-2] + f[i-1]);
    }
    printf("%lld",f[m] * C(m,n));
    return 0;
}
复制代码

 

posted @   行而上  阅读(1327)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)
点击右上角即可分享
微信分享提示