编程题——年会抽奖

链接:https://www.nowcoder.com/questionTerminal/610e6c0387a0401fb96675f58cda8559
来源:牛客网

今年公司年会的奖品特别给力,但获奖的规矩却很奇葩:

  1. 首先,所有人员都将一张写有自己名字的字条放入抽奖箱中;
  2. 待所有字条加入完毕,每人从箱中取一个字条;
  3. 如果抽到的字条上写的就是自己的名字,那么“恭喜你,中奖了!”
    现在告诉你参加晚会的人数,请你计算有多少概率会出现无人获奖?

输入描述:

输入包含多组数据,每组数据包含一个正整数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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值