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 }