P1472 [USACO2.3] 奶牛家谱 Cow Pedigrees 另解
这应该是一种题解区没有的做法。
想数树的形态,考虑 dp。
你会考虑在转移时进行类似合并左右子树的操作,因为将左右子树放在一起,加入根,深度恰好增加
于是非常容易想到考虑
虽然可以强行做前缀和优化去掉一个
首先枚举
于是整个转移就是:
根据定义,初值即为
直接朴素实现即可,复杂度
实现:
int n,k;
int dp[210][110];
const int M=9901;
int main(){
cin>>n>>k;
dp[1][1]=1,dp[3][1]=dp[3][2]=1;
fr1(i,4,n){//其实都可以只枚举奇数,但是是常数优化就无所谓了
fr1(j,2,k+1){//因为深度为0时不合法所以从2开始枚举深度
fr1(p,1,i-2){
dp[i][j]+=((dp[p][j-1]*dp[i-1-p][1]%M+dp[p][1]*dp[i-1-p][j-1]%M)%M-dp[p][j-1]*dp[i-1-p][j-1]%M+M)%M;
dp[i][j]%=M;
}
}
dp[i][1]=dp[i][2];//但在最后必须记得特意给dp[i][1]赋dp[i][2]的值,后面转移可能会用到dp[i][1]
}
cout<<(dp[n][k]-dp[n][k+1]+M)%M<<endl;
ET;
}
AC 记录