当前位置: 代码迷 >> 综合 >> 2016级算法第一次上机——A The stupid owls
  详细解决方案

2016级算法第一次上机——A The stupid owls

热度:80   发布时间:2023-11-26 00:13:56.0

A The stupid owls

时间限制:1000ms   内存限制:65536kb


题目描述

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

错排~

题目分析

如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类型,包括n。

示例代码

#include<cstdio>
long long d(long long n)
{if(n==1)return 0;if(n==2)return 1;elsereturn (n-1)*(d(n-1)+d(n-2));
}
int main()
{long long n;while(scanf("%lld",&n)!=EOF){double y=1;double x=d(n);for(int i=1;i<=n;i++){y=y*i;}printf("%.2lf%%\n",x/y*100);}
}