印章 蓝桥杯


image-20220125135715517


解题思路

动态规划,如下表所示,pp[i] [j]表示买 i 张凑齐 j 种印章的概率

img

题目中有 n 种印章, 每种概率是 1/n;

先来看i<j的时候:因为买 i 张最多只能凑齐 i 种,所以这种情况概率为0

再来看j=1的时候:

​ i=1:dp[i] [1]表示的意思是买 i 张凑齐 1 种的概率,很明显 i == 1 && j == 1 的时候dp[1] [1] = 1,因为你买一张是无论如何都可以凑齐一种的。

​ i > 1:i > 1 && j == 1. 意思就是买 i 张凑齐 1 种印章的概率,意味着买的这 i 张印章是同一种,概率就是 (1/n)^i,但是,我们这 i 张要么是第一种,要么是第二种…( 要么是第k种 ,1 <= k <= n )。最后还要乘上n,所以这个情况 dp[i] [j] = (1/n)^(i-1)

初始状态大致就上面这些了。

最后来看中间的状态 dp[i] [j]:

我们买的第 i 张,有两种状态,一:跟前面买的 i-1 张中有重复的 二:跟前面买的 i-1 张中没有重复的

比如:(总共有5种印章,标号1,2,3,4,5) 我正在买第5张,前面四张凑齐了1,2,3,4号,那么第5张如果也是1,2,3,4号中的一个就表示重复的;如果第5张是5号,就表示没有重复的。

一:有重复的:就表明前面买的 i-1 张,已经凑齐了 j 种。dp[i] [j] = dp[i-1] [j] * ( j / n );

在这里插入图片描述

二:无重复的

前面买的 i-1 张 凑齐了 j-1 种, 我们买的第 i 张与前面的不重复,就又凑齐了一种:dp[i] [j] = dp[i-1] [j-1] * (n-j+1) / n;

在这里插入图片描述

然后把两种情况加起来就是dp[i] [j] 的概率了。

代码

//共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
#include<stdio.h>
#include<math.h>
int n,m;
double pp(int i, int j)
{
    if (!i || !j || i > j)
    {
        return 0;
    }
    else if (i == 1)
    {
        return pow(1.0 / n, j - 1);
    }
    else
    {
        return pp(i - 1, j - 1) * (n - i + 1) / n + pp(i, j - 1) * i / n;
    }
    return 0;
}
int main()
{
    scanf("%d%d", &n, &m);
    if (n == 1)
    {
        printf("1.0000");
    }
    else if (n > m)
    {
        printf("0.0000");
    }
    else
    {
        printf("%.4f", pp(n, m));
    }
    return 0;
}

参考文献

蓝桥杯 试题 算法训练 印章_okok__TXF的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值