AC自动机的专题刷完了...开始刷概率了...
题目大意:
就是现在要从一个软件中找出bug, 这个软件有s个子模块,一共有n种bug,现在每天你可以找到一个bug, 这个bug属于任何一种bug和任何一个子模块都是等可能的, 问需要多少天使得每个子模块都有bug找到, 且一共找到n中不同的bug,求这个天数期望
大致思路:
大致思路见代码注释
代码如下:
Result : Accepted Memory : 8668 KB Time : 266 ms
/* * Author: Gatevin * Created Time: 2014/11/29 16:08:54 * File Name: Asuna.cpp */ //submit language : G++ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; double dp[1010][1010]; /* * 用dp[i][j]表示当前找到了i种病毒,j个子模块已经找到了病毒之后,到达n中病毒,s个子模块的期望天数 * 那么对于点(i, j)可以到达状态 (i, j), (i + 1, j), (i, j + 1), (i + 1, j + 1), 当然到达状态需要在1~n, 1~s之间 * 因为从dp[0][0]出发一定会到达dp[1][1]也就是说i, j不可能只有1个为0, 同时i <= n, j <= s * 那么由于每次转移的代价都是1在上面的范围内 * dp[i][j] = (i*j)/(n*s)*dp[i][j] + (n - i)*j/(n*s)*dp[i + 1][j] + i*(s - j)/(n*s)*dp[i][j + 1] + (n - i)*(s - j)/(n*s)*dp[i + 1][j + 1] + 1(转移代价) * 对于i + 1, j + 1出界的情况就不用加上了,因为不存在这样的转移 * 而且显然有dp[n][s] = 0 * 用两层循环可以算出dp[1][1], 答案dp[0][0] = dp[1][1] + 1 */ int main() { int n,s; while(~scanf("%d %d", &n, &s)) { memset(dp, 0, sizeof(dp)); for(int i = n; i >= 1; i--) for(int j = s; j >= 1; j--) { if(i == n && j == s) continue; if(i < n) dp[i][j] += dp[i + 1][j]*(n - i)*j; if(j < s) dp[i][j] += dp[i][j + 1]*i*(s - j); if(i < n && j < s) dp[i][j] += dp[i + 1][j + 1]*(n - i)*(s - j); dp[i][j] += n*s; dp[i][j] /= (n*s - i*j); } printf("%.4f\n", dp[1][1] + 1); } return 0; }