链接:https://www.nowcoder.com/questionTerminal/610e6c0387a0401fb96675f58cda8559
来源:牛客网
今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:
- 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
- 待所有字条加入完毕,每人从箱中取一个字条;
- 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?
输入描述:
输入包含多组数据,每组数据包含一个正整数n(2≤n≤20)。
输出描述:
对应每一组数据,以“xx.xx%”的格式输出发生无人获奖的概率。
示例1
输入
2
输出
50.00%
**解题思路:**典型的排错问题
n个人取到的都不是自己名字的概率=n个人取到的不是自己名字的序列个数 / n个人可能抽取的所有可能性
因此分两步计算:
1.n个人可能抽取的所有结果:n!
2.n个人取到的都不是自己名字的序列个数:f(n)
假设第一个人取到的不是自己的个数为n-1,
假设第二个人这个时候拿到了第一个人的名字,那么对于第二个人的名字有两种情况:
第一种:第二个人的名字是被第一个人拿到了,也就是a和b互相拿到了对方的名字,那么对于其他的N-1个人来说互相拿错又是一个子问题f(n-2) ;
第二种:第二个人的名字没有被第一个人拿到,则剩下的问题是子问题f(n-1).
f(n) = (n-1)*[f(n-2) + f(n-1)]
#include<iostream>
using namespace std;
int main()
{
long long d[21] = {0,0,1}; //错排数量,预留第一项为0,为输入的n
long long f[21] = {1,1,2}; //阶乘
for(int i = 3; i <= 20; i++)
{
d[i] = (i - 1)*(d[i-1] + d[i-2]); //错排的递推公式
f[i] = f[i-1]* i; //阶乘公式
}
int n ;
while(cin >> n)
{
printf("%.2f%%\n",100.0*d[n]/f[n]); //*100.0,转化为double类型
}
return 0;
}