CCF NOI 1179 错排问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CCF NOI 1179 错排问题相关的知识,希望对你有一定的参考价值。

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置。

题目链接:http://oj.noi.cn/oj/#main/show/1179

 

题目描述

n个编号为1到n的同学手里都有一本书,n本书互不相同,现在把这n本书收起来,再重新分发给同学,要求每个同学必须都有书,并且每个同学现在拿到的书必须不同于之前手里的那本书,问有多少种分发方案?
如n=3有两种分发方案:2 3 1和3 1 2。

输入

第一行输入一个正整数n(1<=n<=20)。

输出

输出一个整数表示方案数。

样例输入

3

样例输出

2

数据范围限制

1<=n<=20

 

分析:

错排问题。公式:f[n] = (n-1)*(f[n-1]+f[n-2])

推导(复制自百度百科):

第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:
⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;
⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法。
需要注意的就是这道题需要用long long
 
AC代码:
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 using namespace std;
 7 
 8 inline void read(int &x)
 9 {
10     x = 0;char ch = getchar(), c = ch;
11     while(ch < 0 || ch > 9)c = ch, ch = getchar();
12     while(ch <= 9 && ch >= 0)x = (x<<1)+(x<<3)+ch - 0, ch = getchar();
13     if(c == -)x = -x;
14 }
15 
16 long long f[30];
17 
18 int main()
19 {
20     int n;
21     read(n);
22     f[1] = 0,f[2] = 1;
23     for(int i = 3;i <= n;++ i)
24         f[i] = (i-1)*(f[i-1]+f[i-2]);
25     printf("%lld\n",f[n]);
26     return 0;
27 }

 

以上是关于CCF NOI 1179 错排问题的主要内容,如果未能解决你的问题,请参考以下文章

CCF NOI 1172 单词数 题解

CCF NOI1047 寻找鞍点

CCF NOI1069

CCF NOI1101(子矩阵求和)

NOI-CCF 1123. A-B (Standard IO)

noi银牌可以签哪些