问题描述
共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
输入格式
一行两个正整数n和m
输出格式
一个实数P表示答案,保留4位小数。
样例输入
2 3
样例输出
0.7500
数据规模和约定
1≤n,m≤20
像这种关于个数和种类的问题,可以用DP的思想解决
#include <bits/stdc++.h>
using namespace std;
double d[21][21];
int main(){
int n,m;
cin>>n>>m;
double p=1.0/n;
for(int i=1;i<=m;i++){
for(int j=1;j<=n;j++){
if(i<j)
d[i][j]=0;
if(j==1)
d[i][j]=pow(p,(i-1));
else
d[i][j]=d[i-1][j]*(1.0*j/n)+d[i-1][j-1]*(1.0*(n-j+1)/n);
}
}
cout<<fixed<<setprecision(4)<<d[m][n];
return 0;
}
- i < j 时 :
概率为0- j = 1 时:
- i = 1 时 为1,
因为买一种有一种的概率为 1
- i > 1 时 (1/n)^(i - 1)
意思是买 i 张但只有一种所以有 (1/n)^i
但是还要这种可能是n种种的任意一种,所以还要乘以 n- i > j 时:
买了 i 张得到了 j 种不同的情况,为两种情况相加,
即 买了 i - 1 张 得到了 j 种,即再买一张还是 j 种的 dp[i] [j] = dp[i-1] [j] * ( j / n )
和 买了 i - 1 张 得到了 j - 1 种,即再买一张是第 j 种的 dp[i] [j] = dp[i-1] [j-1] * (n-j+1) / n