每日OJ_牛客_年会抽奖(错排问题)

牛客_年会抽奖(错排问题)

年会抽奖__牛客网


解析代码

        该题为经典的错排问题

        用A、B、C……表示写着n位友人名字的信封,a、b、c……表示n份相应的写好的信纸。把错装的总数为记作 D(n)。假设把a错装进B里了,包含着这个错误的一切错装法分两类:

  1. b装入A里,这时每种错装的其余部分都与A、B、a、b无关,应有D(n-2)种错装法。
  2. b装入A、B之外的一个信封,这时的装信工作实际是把(除a之外的)n-1份信纸b、c……装入(除B以外 的)n-1个信封A、C……,显然这时装错的方法有D(n-1)种。

        总之在a装入B的错误之下,共有错装法D(n-2)+D(n-1)种。 a装入C,装入D……的n-2种错误之下,同样都有D(n-1)+D(n-2)种错装法,因此D(n)=(n-1)[D(n-1)+D(n- 2)]

所以D(n) = (n-1) [D(n-2) + D(n-1)] 。特殊的,D(1) = 0, D(2) = 1.

        错排的递推公式是:D(n) = (n - 1) [D(n - 2) + D(n - 1)],也就是n - 1倍的前两项和。公式推导可以参考百度百科。 通过这个递推公式可以得到在总数为n的时候,错排的可能性一共有多少种。

        那么要求错排的概率,还需要另一个数值,就是当总数为n的时候,所有的排列组合一共有多少种,也就是n的阶乘。所以结果很简单,就是用公式求出第n项的错排种类,和n的阶乘,然后两者一除, 就是概率了。

#include <iostream>
using namespace std;

int main()
{
    long long d[21] = { 0, 0, 1 }; // 错排数量,预留第一项为0
    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] = i * f[i - 1]; // 阶乘的递推公式
    }
    int n = 0;
    while (cin >> n)
    {
        printf("%.2f%%\n", 100.0 * d[n] / f[n]);
        //用100.0来把结果处理成double,保留两位小数
    }
    return 0;
}
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GR鲸鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值