题目链接:https://vjudge.net/problem/UVA-1264
题目思路:想,从根结点开始每个结点是如何确定下来的,先根节点,他从n个位置中选n个出来,他肯定放在第1个,他是C(n,n),接着想根节点的右子树结点,他能放在那些位置,首先先将根节点的左右子树的而所有节点加起来,然后用C选出右结点的个数,也就是C[根结点左子树结点个数+根结点右子树节点个数][根结点右子树结点个数],根节点右子树结点一定是放在C出来的第一个,然后便可以枚举每个是右子树的结点
AC代码
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
int tree[5000000];
int num[5000000];
long long C[36][36];
long long maxx;
vector<int>vec;
#define mod 9999991
void insert(int root,int val)
{
maxx=max(maxx,(long long)root);
if(tree[root]==0)
{
vec.push_back(root);
tree[root]=val;
num[root]=1;
return;
}
num[root]++;
if(val<tree[root])
insert(root<<1,val);
else
insert(root<<1|1,val);
}
int main()
{
for(int i=0;i<=30;++i)
{
for(int j=0;j<=i;++j)
{
if(j==0||j==i)
C[i][j]=1;
else
C[i][j]=C[i-1][j-1]+C[i-1][j];
}
}
int t;
scanf("%d",&t);
int n;
while(t--)
{
for(int i=0;i<vec.size();++i)
{
tree[vec[i]]=0;
num[vec[i]]=0;
}
vec.clear();
maxx=0;
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
int x;
scanf("%d",&x);
insert(1,x);
}
long long ans=1;
for(int i=0;i<vec.size();i++)
{
if(vec[i]&1)
ans=ans*C[num[vec[i]]+num[vec[i]-1]][num[vec[i]]]%mod;//判断是否是右子树结点,如果是,就C[兄弟子树全部结点个数+自己子树全部节点个数][自己子树全部节点个数]
}
printf("%lld\n",ans);
}
return 0;
}