[Heoi2013]Sao
$ f_{x,j} $ 表示以x为根的子树 x这个点在子树里的排名为j的方案总数
考虑x和儿子的合并
转移时要开一个临时的数组 $ t[] $ 来临时存一下数据
当儿子在x后面时
$$ t_{j+k}=\sum_{j=1}^{size[x]}\sum_{k=0}^{size[son]}C_{j+k-1}^k*C_{size[son]-k+size[x]-j}^{size[son]-k}*f_{x,j}*suf{son,k+1} $$
当儿子在x前面时
$$ t_{j+k}=\sum_{j=1}^{size[x]}\sum_{k=1}^{size[son]}C_{j+k-1}^{k}C_{size[x]-j+size[son]-k}^{size[son]-k}*pre_{son,k}*f_{x,j} $$
#pragma GCC optimize("O3") #include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <ctime> #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define rint register int #define dd double using namespace std; char rea=0; inline void read(int &x) { x=0; while(rea<'0'||rea>'9') rea=getchar(); while(rea>='0'&&rea<='9') x=x*10+rea-'0',rea=getchar(); } inline void readchar(char &x) { while(rea!='<'&&rea!='>') rea=getchar(); x=rea; } const int N=1006; const int mod=1000000007; int first[N],nt[N*2],ver[N*2],w[N*2],e; void addbian(int u,int v,int _w) { ver[e]=v; w[e]=_w; nt[e]=first[u]; first[u]=e++; } ll qpow(ll a,int ci) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mod; a=a*a%mod; ci>>=1; } return ans%mod; } ll jie[N],jieni[N]; void chu() { int i; jie[0]=1; for(i=1;i<N;++i) jie[i]=jie[i-1]*i%mod; jieni[N-1]=qpow(jie[N-1],mod-2); for(i=N-2;i;--i) jieni[i]=jieni[i+1]*(i+1)%mod; jieni[0]=1; } inline ll C(int n,int m) { if(n<0||m<0||n<m) return 0; return jie[n]*jieni[m]%mod*jieni[n-m]%mod; } int T; int n; ll f[N][N],t[N]; ll pr[N][N],ho[N][N]; int fa[N],size[N]; void dp(int x) { f[x][1]=1; size[x]=1; int i,j,k,p; for(i=first[x];i!=-1;i=nt[i]) { if(ver[i]==fa[x]) continue; fa[ver[i]]=x; dp(ver[i]); for(j=size[x]+size[ver[i]];~j;--j) t[j]=0; if(w[i]) { for(j=size[x];j;--j) for(k=size[ver[i]]-1;~k;--k) t[j+k]=(t[j+k]+C(j+k-1,k)*C(size[ver[i]]-k+size[x]-j,size[ver[i]]-k)%mod*f[x][j]%mod*ho[ver[i]][k+1]%mod)%mod; } else //儿子比x小 { for(j=size[x];j;--j) for(k=size[ver[i]];k;--k) t[j+k]=(t[j+k]+f[x][j]*pr[ver[i]][k]%mod*C(j+k-1,k)%mod*C(size[x]-j+size[ver[i]]-k,size[ver[i]]-k)%mod)%mod; } size[x]+=size[ver[i]]; for(j=size[x];j;--j) f[x][j]=t[j]; } for(i=1;i<=size[x];++i) pr[x][i]=(f[x][i]+pr[x][i-1])%mod; for(i=size[x];i;--i) ho[x][i]=(f[x][i]+ho[x][i+1])%mod; } int main(){ //freopen("in.in","r",stdin); //freopen("zout.out","w",stdout); rint i,j; int tin1,tin2; char op; chu(); read(T); while(T--) { mem(first,-1); e=0; mem(f,0); mem(fa,0); mem(size,0); mem(ho,0); mem(pr,0); read(n); for(i=1;i<n;++i) { read(tin1); readchar(op); read(tin2); ++tin1; ++tin2; addbian(tin1,tin2,(op=='<')); addbian(tin2,tin1,(op=='>')); } fa[1]=-1; dp(1); ll as=0; for(i=1;i<=size[1];++i) as=(as+f[1][i])%mod; printf("%lld\n",as%mod); } }
表示脑子有些混沌...