題目大意:給定一個1-n的排列,依次將這些數插入到二叉排序樹中,問總共有多少個排列使得構成的二叉樹和給定的排列構成的二叉樹相同
本題的思路就是:先構成要求的二叉排序樹,然後再在樹上進行dp
狀態轉移為:dp[rt] = dp[lson]*dp[rson]*c(lson,sum);
lson 表示左子樹的點的個數,sum表示左右子樹點的個數之和。
c(a,b) 表示b中過選擇a個的組合數。狀態轉移應該是比較好理解的吧
代碼寫的比較挫,畢竟不常寫二叉樹
#include <iostream>#include <stdio.h>#include <string.h>using namespace std;#define mod 9999991struct note{ int val,l,r,size; long long dp;}dat[100];int kk;void init(){ for(int i = 0;i < 100;i++) { dat[i].l = dat[i].r = -1; dat[i].val = 0; dat[i].dp = 1; dat[i].size = 1; }}void insert(int rt,int val){ if(val < dat[rt].val) { if(dat[rt].l == -1) { dat[rt].l = kk; dat[kk].val = val; kk++; return; }else insert(dat[rt].l,val); }else { if(dat[rt].r == -1) { dat[rt].r = kk; dat[kk].val = val; kk++; return; }else insert(dat[rt].r,val); }}long long c[100][100];void C(){ int i,j; c[0][0]=1; for(i=1;i<40;i++) //自訂 for(j=0;j<=i;j++) c[i][j]=(j==0)?c[i-1][j]:c[i-1][j]+c[i-1][j-1]; //公式}void dfs(int rt){ if(dat[rt].l == -1 && dat[rt].r == -1) { return; } if(dat[rt].l != -1) dfs(dat[rt].l); if(dat[rt].r != -1) dfs(dat[rt].r); if(dat[rt].l != -1 && dat[rt].r != -1) { dat[rt].size = dat[dat[rt].l].size + dat[dat[rt].r].size + 1; int cc = c[ dat[rt].size-1 ][ dat[dat[rt].l].size ]; dat[rt].dp = cc*dat[dat[rt].l].dp * dat[dat[rt].r].dp%mod; }else if(dat[rt].l == -1) { dat[rt].size = dat[ dat[rt].r ].size+1; dat[rt].dp = dat[dat[rt].r].dp; }else { dat[rt].size = dat[ dat[rt].l ].size+1; dat[rt].dp = dat[dat[rt].l].dp; }}int main(){ C(); //cout << c[20][10]; int t; cin >> t; while(t--) { init(); int n; cin >> n; int tt; kk = 2; for(int i = 0;i < n;i++) { cin >> tt; if(i == 0) dat[1].val = tt; else insert(1,tt); } dfs(1); cout << dat[1].dp << "\n"; } return 0;}