题目描述
Bamboo recently bought an owl for sending and receiving letters. Every owl will bring a letter to exactly one person, so normally Bamboo's owl will only bring letters for her.
Although most owls sold in the magical stores are extremely conscientious almost all the time, sometimes they can also make mistakes. For example, on one occasion Bamboo's owl brought a letter to her roommate Eve, and Eve's owl brought a letter to Bamboo .The two stupid owls made mistakes at the same time!
What's worse, if there were n people, each with a stupid owl, so that every one might get a wrong letter . So what the probability of no one getting his or her correct letter?
输入
The input file will contain a list of positive integers n, one per line(0<n<25)。
输出
For each integer n in the input, output the probability(in percentage form) of the n people all receiving a letter that ought to be sent to another one.
Print each output in one line. Please keep two decimals.
输入样例
2
输出样例
50.00%
HINT
错排~
思路
本题是一个典型的错排问题。
关于错排问题,可以参考百度百科:
https://baike.baidu.com/item/%E9%94%99%E6%8E%92%E5%85%AC%E5%BC%8F/10978508?fr=aladdin
以下关于错排公式的推导均摘自百度。
当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数用D(n)表示,那么D(n-1)就表示n-1个编号元素放在n-1个编号位置,各不对应的方法数,其它类推.
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:
⑴把它放到位置n,那么,对于剩下的n-1个元素,由于第k个元素放到了位置n,剩下n-2个元素就有D(n-2)种方法;
⑵第k个元素不把它放到位置n,这时,对于这n-1个元素,有D(n-1)种方法;
综上得到:
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.
下面通过这个递推关系推导通项公式:
为方便起见,设D(k) = k! N(k), k = 1, 2, …, n,
则N(1) = 0, N(2) = 1/2.
n ≥ 3时,n! N(n) = (n-1) (n-1)! N(n-1) + (n-1)! N(n-2)
即 nN(n) = (n-1) N(n-1) + N(n-2)
于是有
N(n) - N(n-1) = - [N(n-1) - N(n-2)] / n = (-1/n) [-1/(n-1)] [-1/(n-2)]…(-1/3) [N(2) - N(1)] = (-1)^n / n!.
因此
N(n-1) - N(n-2) = (-1)^(n-1) / (n-1)!,
N(2) - N(1) = (-1)^2 / 2!.
相加,可得
N(n) = (-1)^2/2! + … + (-1)^(n-1) / (n-1)! + (-1)^n/n!
因此
D(n) = n! [(-1)^2/2! + … + (-1)^(n-1)/(n-1)! + (-1)^n/n!]
此即错排公式。
根据错排公式,我们可以写出一个递推函数用来求出d(n),d(n)即所有全排错的事件总数,再除以全部基本事件总数n!即为概率。
注意此题的一个坑点,所有数据都用long long类型。
参考代码
1 //递归版 2 #include<stdio.h> 3 double owl(int n); 4 int main() 5 { 6 int n; 7 while(scanf("%d",&n) == 1){ 8 double result = owl(n); 9 printf("%.2f ",result); 10 } 11 } 12 13 double owl(int n) 14 { 15 if(n == 2) 16 return 1/2; 17 else{ 18 19 } 20 }
1 //非递归版 2 #include<stdio.h> 3 int main() 4 { 5 int n,i; 6 double owl[25]; 7 double temp = 0.5; 8 owl[2] = 0.5; 9 for(i = 3;i < 25;i++){ 10 temp = temp * (-1) /(i * 1.0); 11 owl[i] = owl[i-1] + temp; 12 } 13 for(i = 2;i < 25;i++) 14 owl[i] = owl[i] * 100; 15 while(scanf("%d",&n) == 1) 16 printf("%.2f%% ",owl[n]); 17 }