题目:
资源限制
时间限制:1.0s 内存限制:256.0MB
问题描述
共有n种图案的印章,每种图案的出现概率相同。小A买了m张印章,求小A集齐n种印章的概率。
输入格式
一行两个正整数n和m
输出格式
一个实数P表示答案,保留4位小数。
样例输入
2 3
样例输出
0.7500
数据规模和约定
1≤n,m≤20
解题代码:
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.StreamTokenizer; public class Seal { public static void main(String[] args) throws IOException { StreamTokenizer st = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); st.nextToken(); int n = (int) st.nval; st.nextToken(); int m = (int) st.nval; double[][] p = new double[m + 1][n + 1]; System.out.printf("%.4f", probability(p, n, m)); } public static double probability(double[][] p, int n, int m) { double x = 1.0 / n; for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) { if (i < j) { p[i][j] = 0.0; } if (j == 1){ p[i][j] = Math.pow(x, i-1); } else{ p[i][j] = p[i-1][j] * (j*x) + p[i-1][j-1] * ((n-j+1)*x); } } } return p[m][n]; } }
解题思路:
这里是怕我忘记,所以需要记忆一下
后面的概率需要前面的概率支持,就使用动态规划(DP),一般来说都是使用二维数组解题。
又因为本题有两个参数,所以可以猜测使用二维数组dp[i][p]来表示 买 i 个其中有 j 种不同的概率。
分类讨论:
- 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