[每日一题] 89. 发邮件(错排问题、递归)

1. 题目来源

链接:发邮件
来源:牛客网

2. 题目说明

NowCoder每天要给很多人发邮件。有一天他发现发错了邮件,把发给A的邮件发给了B,把发给B的邮件发给了A。于是他就思考,要给n个人发邮件,在每个人仅收到1封邮件的情况下,有多少种情况是所有人都收到了错误的邮件?
即没有人收到属于自己的邮件。

输入描述:

输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。

输出描述:

对应每一组数据,输出一个正整数,表示无人收到自己邮件的种数。

示例:

输入
2
3
输出
1
2

3. 题目解析

经典的装错信封问题,该题目的核心在于递归的思想,具体参见解题思路。
用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。
把错装的总数为记作Der(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:

  1. b装入A里,这时每种错装的其余部分都与A、B、a、b无关,应有Der(n-2)种错装法。
  2. b装入A、B之外的一个信封,这时的装信工作实际是把(除a之外的)n-1份信纸b、c……装入(除B以外的)n-1个信封A、C……,显然这时装错的方法有Der(n-1)种。

总之在a装入B的错误之下,共有错装法Der(n-2)+Der(n-1)种。
a装入C,装入Der……的n-2种错误之下,同样都有Der(n-1)+Der(n-2)种错装法,因此
Der(n)=(n-1)*[Der(n-1)+Der(n-2)]

4. 代码展示

// write your code here cpp
#include <bits/stdc++.h>

using namespace std;

int main() {
    long long der[21] = {0, 0, 1};
    for (int i = 3; i < 21; ++i)
        der[i] = (i - 1) * (der[i - 2] + der[i - 1]);
    int n;
    while (cin >> n) 
        cout << der[n] << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值