USACO Cow Pedigrees 【Dp】
一道经典Dp.
定义dp[i][j] 表示由i个节点,j 层高度的累计方法数
状态转移方程为: 用i个点组成深度最多为j的二叉树的方法树等于组成左子树的方法数
乘于组成右子树的方法数再累计。
& / \ @ # / \ @ @
如图中 & 为顶点, @ 为左子树, # 为右子树
需要注意的是,左子树的节点数目同样也为奇数
然后遍历一遍从k = 1 到 i - 2, 考虑上一层所有的左/右子树方法数再作累加
最后输出答案的时候减去上一层累加数即可
/* ID: wushuai2 PROG: nocows LANG: C++ */ //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <fstream> #include <cstring> #include <cmath> #include <stack> #include <string> #include <map> #include <set> #include <list> #include <queue> #include <vector> #include <algorithm> #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define Abs(x) (((x) > 0) ? (x) : (-(x))) #define MOD 1000000007 #define pi acos(-1.0) #define RV(num) ((num) > 0 ? 0 : 1) using namespace std; typedef long long ll ; typedef unsigned long long ull ; typedef unsigned int uint ; typedef unsigned char uchar ; template<class T> inline void checkmin(T &a,T b){if(a>b) a=b;} template<class T> inline void checkmax(T &a,T b){if(a<b) a=b;} const double eps = 1e-7 ; const int M = 660000 ; const ll P = 10000000097ll ; const int INF = 0x3f3f3f3f ; const int MAX_N = 20 ; const int MAXSIZE = 101000000; int N, K; int dp[220][120]; int main() { ofstream fout ("nocows.out"); ifstream fin ("nocows.in"); int i, j, k, l, m, n, t, s, c, w, q, num; fin >> N >> K; for(i = 1; i <= N; ++i) dp[1][i] = 1; for(j = 1; j <= K; ++j){ for(i = 1; i <= N; ++i){ if(i & 1){ for(k = 1; k <= i - 2; ++k){ if(k & 1){ dp[i][j] = (dp[k][j - 1] * dp[i - 1 - k][j - 1] + dp[i][j]) % 9901; } } } } } fout << (dp[N][K] - dp[N][K - 1] + 9901) % 9901 << endl; fin.close(); fout.close(); return 0; }