题意:问给你m个数取出n个数随意排列有多少中方法可以得到和给定分数一样的二叉树结构。
思路:算是排列组合吧,首先不用管选的是哪n个数,因为结构和数是多少没有关系,只和数的大小关系有关,因此只要算出给定数有多少中排法再乘以所以组合种类数即可。
不过看起来还是有点困难啊。这里我现将给定的数建立二叉树,然后dfs遍历,每个结点必须在它子节点的前面。我们可以看作是n个空位,每到一结点,让该结点为它自己及其子节点申请空位,然后遍历它的子节点时再在他根节点申请的空位的基础上申请空位,反正我当时这么想的,你可能没明白,那就看代码吧。。。。。说不清了。
#include<iostream> #include<cstdio> #define mod 1000003 using namespace std; int f[1005][1005]; int tt,m,n; int tnum; int a; long long int ans; struct node { int l,r; int val; int num; }t[100005]; int cc() { f[0][0]=1; for(int i=1;i<=1000;i++) { f[i][0]=f[i][i]=1; for(int j=1;j<i;j++) { f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod; } } // for(int i=0;i<=10;i++) // { // for(int j=0;j<=i;j++) // { // cout<<f[i][j]<<' '; // } // cout<<endl; // } } void build(int va,int rot) { if(t[rot].val==-1) { t[rot].val=va; t[rot].l=-1; t[rot].r=-1; t[rot].num=1; } else { if(va<t[rot].val) { if(t[rot].l==-1) { t[rot].l=++tnum; t[tnum].val=-1; } build(va,t[rot].l); } else { if(t[rot].r==-1) { t[rot].r=++tnum; t[tnum].val=-1; } build(va,t[rot].r); } t[rot].num=1; if(t[rot].r!=-1)t[rot].num+=t[t[rot].r].num; if(t[rot].l!=-1)t[rot].num+=t[t[rot].l].num; } } void dfs(int rot,int ss) { ans=(ans*(f[ss][t[rot].num]*1ll))%mod; if(t[rot].l!=-1) { dfs(t[rot].l,t[rot].num-1); } if(t[rot].r!=-1)dfs(t[rot].r,t[rot].num-1-((t[rot].l==-1)?0:t[t[rot].l].num)); } int main() { cc(); scanf("%d",&tt); while(tt--) { tnum=1; t[1].val=-1; t[1].num=0; scanf("%d%d",&m,&n); for(int i=1;i<=m;i++) { scanf("%d",&a); build(a,1); } ans=1; dfs(1,m); cout<<(ans*(f[n][m]*1ll))%mod<<endl; } return 0; }