试题 算法训练 印章
问题述
共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
输入格式
一行两个正整数n和m
输出格式
一个实数P表示答案,保留4位小数。
样例输入
2 3
样例输出
0.7500
数据规模和约定
1≤n,m≤20
/*
dp[i][j]:买了i个印章,集齐了j种印章的概率
特殊情况: 买1个印章,集齐1种印章的概率 dp[1][1] = 1;
i < j: 不够凑齐j种 即dp[i][j] = 0
j == 1: 买了i个,但只有一种 每一种的概率是(1 / n) ^ i 即dp[i][j] = (i / n) ^ i * n = (i / n) ^ (i - 1)
一般情况: 第i个印章和前j个重复, 即第i个印章在前j中选一个 或者 第i个印章和前j个不重复, 即第i个印章不在前j中选一个
dp[i][j] = dp[i][j] = dp[i - 1][j] * ((double)j / n) + dp[i - 1][j - 1] * ((double)n - j + 1) / n;
*/
#include <iostream>
#include <cmath>
using namespace std;
const int N = 30;
double dp[N][N];
int n, m;
int main()
{
cin >> n >> m;
dp[1][1] = 1;
for(int i = 1; i <= m; i ++)
{
for(int j = 1; j <= n; j ++)
{
if(i < j)
dp[i][j] = 0;
else if(j == 1)
dp[i][j] = pow((double)1 / n, i - 1);
else
dp[i][j] = dp[i - 1][j] * ((double)j / n) + dp[i - 1][j - 1] * ((double)n - j + 1) / n;
}
}
printf("%.4f", dp[m][n]);
return 0;
}