# 428. [2018] Team ordinary job title of count
Good model into question
Count the number of labels have become so legitimate tree.
Legal restrictions:
1. Reference numeral root subtree is larger than
2. If the son is all the leaves, there are number of B
3. If there is a son, not a leaf, there are number of A
Then consider DP
The case of direct enumeration root son
cdq partition NTT is very disgusting
Not only is his own roll, or roll each other
After some simplification and translation, it can be converted into a form cdq partition NTT:
How how to do good.
Anyway, I finally pushed equation has the following characteristics (formulas do not write):
For convenience, Imperial g [0], f [0], g [1], f [1] is 0
For f, a fixed, a pan right moment, and then is cdq partition of the template title
For g, when partition sections l cdq not 0 to F as [l, mid], G as [ql, qr], and G as [l, mid], F as [ql, qr] do two all over
This is actually the rest g [n] = g [0] * f [n], but the g [0] = 0, so do not control
Code:
const int N=240000+5; int jie[N],inv[N]; int f[N],g[N]; int n,sa,sb; int ta[N],b[N],a[N]; void divi(int l,int r,int ql,int qr){ // cout<<" divi "<<l<<" "<<r<<" ql "<<ql<<" qr "<<qr<<endl; if(l==0&&r==1){ f[0]=f[1]=g[0]=g[1]=0; return; } if(l==r){ f[l]=ad(mul(f[l],jie[l-1]),b[l-1]); g[l]=ad(f[l],mul(g[l],jie[l-1])); f[l]=mul(f[l],inv[l-1]); g[l]=mul(g[l],inv[l]); return; } int mid=(l+r)>>1; int qmd=(ql+qr)>>1; divi(l,mid,ql,qmd); Poly A,G; A.resize(qr-ql+1); G.resize(mid-l+1); for(reg i=ql;i<=qr;++i){ A[i-ql]=a[i]; } for(reg i=l;i<=mid;++i){ G[i-l]=g[i]; } A*=G; for(reg i=mid+1;i<=r;++i){ f[i]=ad(f[i],A[i-l]); } if(l==0){ Poly F;G.clear(); F.resize(mid-l+1); G.resize(mid-l+1); for(reg i=l;i<=mid;++i){ F[i-l]=f[i]; G[i-l]=g[i]; } F=F*G; for(reg i=mid+1;i<=r;++i){ g[i]=ad(g[i],F[i]); } }else{ Poly F;G.clear(); F.resize(qr-ql+1); G.resize(mid-l+1); for(reg i=l;i<=mid;++i){ G[i-l]=g[i]; } for(reg i=ql;i<=qr;++i){ F[i-ql]=f[i]; } F=F*G; for(reg i=mid+1;i<=r;++i){ g[i]=ad(g[i],F[i-l]); } F.clear();G.clear(); F.resize(mid-l+1); G.resize(qr-ql+1); for(reg i=ql;i<=qr;++i){ G[i-ql]=g[i]; } for(reg i=l;i<=mid;++i){ F[i-l]=f[i]; } F=F*G; for(reg i=mid+1;i<=r;++i){ g[i]=ad(g[i],F[i-l]); } } divi(mid+1,r,ql,qmd); } int main(){ rd(n);rd(sa);rd(sb);int x; for(reg i=1;i<=sa;++i){rd(x);ta[x]=1;} for(reg i=1;i<=sb;++i){rd(x);b[x]=1;} if(n==1){ puts("1");return 0; } int m; for(m=1;m<=n;m<<=1); jie[0]=1; for(reg i=1;i<=m;++i) jie[i]=mul(jie[i-1],i); inv[m]=qm(jie[m],mod-2); for(reg i=m-1;i>=0;--i) inv[i]=mul(inv[i+1],i+1); for(reg i=1;i<=m;++i){ a[i]=mul(ta[i-1],inv[i-1]); } a[0]=0; divi(0,m-1,0,m-1); ll ans=f[n]; ans=mul(ans,jie[n-1]); ot(ans); return 0; }
树形结构很巧妙啊
f,g互相卷的分治NTT第一次写,还是举一个0,1,2,3,4,5,6,7的例子最好理解了!