PAT乙级(Basic Level)练习题 发邮件

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

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

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

输入例子:

2
3

输出例子:

1
2

\color{blue}解题思路:
这道题的关键是抽象发邮件的过程,找到规律,不能局限于发邮件的细节。
规律:
假设有n个人,现在我将第n张邮件发给其他人,总共有n - 1种情况(不能发给自己)。
假设收到第n张邮件的人为m,辣么当我们发送第m张邮件时,有两种选择,
第一种,我们把第m张邮件发送给第n个人(第n、m分别收到了对方的邮件),剩下的n - 2个人的子问题,有f(n - 2)种情况;
第二种,我们把第m张邮件发给不是第n个人也不是第m个人,那么问题有转换为n - 1人的子问题,有f(n - 1)种情况。
因此得出递推公式 f(n) = (n - 1) * (f(n - 1) + f(n - 2))(n ≥ 3).

\color{blue}代码实现:

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    int n = 0;
    //将1≤n≤20的所有情况存储起来
    long long fTable[21] = {0, 0, 1};
    for (int i = 3; i < 21; ++i) {
   		//递推公式f(n) = (n - 1) * (f(n - 1) + f(n - 2))
        fTable[i] = (i - 1) * (fTable[i - 1] + fTable[i - 2]);
    }
    //scanf返回值为正确输入数据的变量个数,当一个变量都没有成功获取数据时,此时返回-1
    while (scanf("%d", &n) != - 1) {
    	//直接查表即可
        printf("%lld\n", fTable[n]);
    }
    return 0;
}

在这里插入图片描述

发布了1005 篇原创文章 · 获赞 269 · 访问量 22万+

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/104662557
今日推荐