#428. 【集训队作业2018】普通的计数题

模型转化好题

所以变成统计有标号合法的树的个数。

合法限制:

1.根标号比子树都大

2.如果儿子全是叶子,数量B中有

3.如果存在一个儿子不是叶子,数量A中有

然后考虑DP

直接枚举根的儿子的情况

cdq分治NTT还是很恶心的

不光是自己卷自己,还是互相卷

进行一番化简和平移之后,可以转化为cdq分治NTT的形式:

怎么好做怎么来。

反正我最后推的式子有如下特点(式子就不写了):

为了方便,钦定g[0],f[0],g[1],f[1]都是0

对于f,a是固定的,a向右平移一下,然后就是cdq分治的模板题了

对于g,当cdq的分治区间l不是0的时候,要F作为[l,mid],G作为[ql,qr],和G作为[l,mid],F作为[ql,qr]做两遍

这样其实剩下g[n]=g[0]*f[n],但是g[0]=0,所以不用管

代码:

const int N=+;
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==&&r==){
f[]=f[]=g[]=g[]=;
return;
}
if(l==r){
f[l]=ad(mul(f[l],jie[l-]),b[l-]);
g[l]=ad(f[l],mul(g[l],jie[l-]));
f[l]=mul(f[l],inv[l-]);
g[l]=mul(g[l],inv[l]);
return;
}
int mid=(l+r)>>;
int qmd=(ql+qr)>>;
divi(l,mid,ql,qmd);
Poly A,G;
A.resize(qr-ql+);
G.resize(mid-l+);
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+;i<=r;++i){
f[i]=ad(f[i],A[i-l]);
} if(l==){
Poly F;G.clear();
F.resize(mid-l+);
G.resize(mid-l+);
for(reg i=l;i<=mid;++i){
F[i-l]=f[i];
G[i-l]=g[i];
}
F=F*G;
for(reg i=mid+;i<=r;++i){
g[i]=ad(g[i],F[i]);
}
}else{
Poly F;G.clear();
F.resize(qr-ql+);
G.resize(mid-l+);
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+;i<=r;++i){
g[i]=ad(g[i],F[i-l]);
}
F.clear();G.clear();
F.resize(mid-l+);
G.resize(qr-ql+);
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+;i<=r;++i){
g[i]=ad(g[i],F[i-l]);
}
}
divi(mid+,r,ql,qmd);
}
int main(){
rd(n);rd(sa);rd(sb);int x;
for(reg i=;i<=sa;++i){rd(x);ta[x]=;}
for(reg i=;i<=sb;++i){rd(x);b[x]=;}
if(n==){
puts("");return ;
}
int m;
for(m=;m<=n;m<<=);
jie[]=;
for(reg i=;i<=m;++i) jie[i]=mul(jie[i-],i);
inv[m]=qm(jie[m],mod-);
for(reg i=m-;i>=;--i) inv[i]=mul(inv[i+],i+); for(reg i=;i<=m;++i){
a[i]=mul(ta[i-],inv[i-]);
}
a[]=; divi(,m-,,m-);
ll ans=f[n];
ans=mul(ans,jie[n-]);
ot(ans);
return ;
}

树形结构很巧妙啊

f,g互相卷的分治NTT第一次写,还是举一个0,1,2,3,4,5,6,7的例子最好理解了!

最新文章

  1. DTO对象
  2. Python基础(深、浅拷贝)
  3. 导出 C/C++ API 给 Lua 使用[转]
  4. emacs auto-complete
  5. 1006 最长公共子序列Lcs
  6. 3、颜色的字符串、十进制、十六进制相互转换(color convert between dec、hex and string )
  7. go开发环境配置
  8. 谈谈Nullable&lt;T&gt;的类型转换问题
  9. onActivityResult不执行 或者 onActivityResult的解决方法
  10. 走向DBA[MSSQL篇] 详解游标
  11. 两个java项目,跨域访问时,浏览器不能正确解析数据问题
  12. SQL之case when then用法(用于分类统计)
  13. 关于library cache lock和row cache lock产生的常见原因
  14. linux每日命令(37):top命令
  15. 监督学习之knn算法
  16. Linux进程内存分析和内存泄漏定位
  17. WebView中JS调用Android Method 遇到的坑整理
  18. 选中TreeView的某节点,并加背景颜色
  19. 玩转X-CTR100 l STM32F4 l DHT11温湿度传感器
  20. KVM-Introduce

热门文章

  1. bind()的模拟实现
  2. vc 识别移动硬盘 U盘,本地硬盘
  3. Python 变量与数据类型
  4. DRF初识
  5. .git文件夹太大问题及解决方法
  6. EF 中获取 TableAttribute的值,即数据库中真实的表名
  7. 杂项-公司:AT&amp;T
  8. poi 3669 meteor shower (bfs)
  9. PAT甲级——A1079 Total Sales of Supply Chain
  10. java基础之final关键字