神、上帝以及老天爷(错位排序)

Description

协会活动为了活跃气氛,组织者举行了一个别开生面、奖品丰厚的抽奖活动,这个活动的具体要求是这样的: 首先,所有参加晚会的人员都将一张写有自己名字的字条放入抽奖箱中; 然后,待所有字条加入完毕,每人从箱中取一个字条; 最后,如果取得的字条上写的就是自己的名字,那么“恭喜你,中奖了!” 大家可以想象一下当时的气氛之热烈,毕竟中奖者的奖品是大家梦寐以求的Twins签名照呀!不过,正如所有试图设计的喜剧往往以悲剧结尾,这次抽奖活动最后竟然没有一个人中奖! 我的神、上帝以及老天爷呀,怎么会这样呢? 不过,先不要激动,现在问题来了,你能计算一下发生这种情况的概率吗? 不会算?难道你也想以悲剧结尾?!

Input

输入数据的第一行是一个整数C,表示测试实例的个数,然后是C 行数据,每行包含一个整数n(1< n<=20),表示参加抽奖的人数。

Output

对于每个测试实例,请输出发生这种情况的百分比,每个实例的输出占一行, 结果保留两位小数(四舍五入),具体格式请参照sample output

Sample Input

1
2

Sample Output

50.00%


解题思路:这是一个错位排序的问题,在这里谢谢关于错位排序的原理以及思路。

错位排列:

第一步,错排第一号元素(将第一号元素排在k位置),有n-1种方法。

第二步,错排其余n-1个元素。紧接第一步的结果,若第一号元素落在第k个位置,第二步就先把K排好

1、 k 号元素排在第1个位置,留下的 n - 2 个元素在与它们的编号集相等的位置集上“错排”,有 f(n -2) 种方法;
2、 k 号元素不排第 1 个位置,这时可将第 1 个位置“看成”第 k 个位置(也就是说本来准备放到k位置为元素,可以放到1位置中),于是形成(包括 k 号元素在内的) n - 1 个元素的“错排”,有 f(n - 1) 种方法。据加法原理,完成第二步共有 f(n - 2)+f(n - 1) 种方法。 
根据乘法原理, n 个不同元素的错排种数 

错排公式 f(1)=0,f(2)=1;f(n)=(n-1)(f(n-1)+f(n-2))

 1 #include <iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cmath>
 6 using namespace std;
 7 #define maxn 200
 8 int main()
 9 {
10     int t,n;
11     double a[maxn];
12      a[1]=0;a[2]=1;
13     for(int i=3;i<=22;i++)
14     {
15         a[i]=(i-1)*(a[i-1]+a[i-2]);
16     }
17     scanf("%d",&t);
18     while(t--)
19     {
20         double sum=1;
21         scanf("%d",&n);
22 
23         for(int i=1;i<=n;i++)
24             sum*=i;
25         printf("%.2lf%%
",a[n]/sum*100);
26     }
27 }
原文地址:https://www.cnblogs.com/wkfvawl/p/8998468.html