题目:http://community.topcoder.com/stat?c=problem_statement&pm=13117&rd=15950
看到树,又是与节点有关,通常是dp,dp[v][t] 表示在以v为root的subtree上有t个eagle时满足条件的概率。一个注意点是求二项系数数组C[]时,由于值太大。要用double,不能用long long, long long 会溢出。
#include <algorithm> #include <functional> #include <numeric> #include <utility> #include <iostream> #include <sstream> #include <iomanip> #include <bitset> #include <string> #include <vector> #include <stack> #include <deque> #include <queue> #include <set> #include <map> #include <cstdio> #include <cstdlib> #include <cctype> #include <cmath> #include <cstring> #include <ctime> #include <climits> using namespace std; #define CHECKTIME() printf("%.2lf ", (double)clock() / CLOCKS_PER_SEC) typedef pair<int, int> pii; typedef long long llong; typedef pair<llong, llong> pll; #define mkp make_pair /*************** Program Begin **********************/ const int MAX_N = 51, MAX_K = 101; double dp[MAX_N][MAX_K]; double C[MAX_K][MAX_K]; // 二项系数,注意:用 long long 会溢出 class EagleInZoo { public: vector < vector<int> > childs; double rec(int v, int t) { if (1 == t) { return 1.0; } double & res = dp[v][t]; if (res > -0.5) { return res; } if (childs[v].size() == 0 && t > 1) { // 该节点无 child 且t > 1。最后一仅仅一定无法停留 res = 0; return res; } res = 0; for (int i = 0; i < childs[v].size(); i++) { int x = childs[v][i]; int c = childs[v].size(); for (int j = 0; j <= t - 2; j++) { res += (1.0 / c) * C[t-2][j] * pow(1.0 / c, j) * pow( 1.0 * (c-1) / c, t-2-j) * rec(x, j + 1); } } return res; } double calc(vector <int> parent, int K) { for (int i = 0; i < MAX_N; i++) { for (int j = 0; j < MAX_K; j++) { dp[i][j] = -1.0; } } childs.resize(parent.size() + 1); for (int i = 0; i < parent.size(); i++) { childs[ parent[i] ].push_back(i + 1); } // calculate C[] C[0][0] = 1; for (int i = 1; i <= K - 1; i++) { C[i][0] = C[i][i] = 1; for (int j = 1; j < i; j++) { C[i][j] = C[i - 1][j] + C[i - 1][j - 1]; } } return rec(0, K); } }; /************** Program End ************************/