这个题意说人话就是:一棵带标号的有根树,编号满足堆性质,根节点有$x$个儿子是叶子($x\in A$),另外的$2$个儿子也是这样的一棵树,求不同的树的个数

设$f_n$为答案,枚举那两棵子树的大小$i,j$,那么$f_i=\frac12\sum\limits_{1\leq j,k\lt i}[i-1-j-k\in A]\binom{i-1}j\binom{i-1-j}kf_jf_k$,$f_1=1$,直接做是$O(n^3)$的

把组合数拆开,记$a_i=[i\in A]\frac1{i!},f'_i=\frac{f_i}{i!},g_i=\sum\limits_{j+k=i}f'_jf'_k$,那么$f'_i=\frac1{2i}\sum\limits_{j+k=i-1}a_jg_k$,按照这个直接做,每次更新$g$,时间复杂度为$O(n^2)$

因为$f,g$的递推式都是卷积,所以考虑分治FFT,这种类CDQ分治的分治FFT主要解决形如$f_i=\sum\limits_{j+k=i}g_jh_k$的递推式,其中$g,h$中至少一个与$f$有关

如果当前分治到$[l,r]$,先递归进$[l,mid]$,然后算递推式中$j\in[l,mid],i\in[mid+1,r]$的部分,一次卷积就可以了

需要注意的是如果$g,h$都与$f$有关,那么我们还要处理$j,k\in[l,mid],i\in[mid+1,r]$的情况,但因为是分治结构,所以这种情况只会在$l=1$时出现,于是只需在$l\gt1$时再做一次即可,如果$g=h$那么直接把答案$\times2$就行了

#include<stdio.h>
#include<algorithm>
#include<string.h>
using namespace std;
typedef long long ll;
const int mod=998244353;
int mul(int a,int b){return(ll)a*b%mod;}
int ad(int a,int b){return(a+b)%mod;}
int de(int a,int b){return(a-b)%mod;}
void inc(int&a,int b){(a+=b)%=mod;}
int pow(int a,int b){
	int s=1;
	while(b){
		if(b&1)s=mul(s,a);
		a=mul(a,a);
		b>>=1;
	}
	return s;
}
int rev[524288],N,iN;
void pre(int n){
	int i,k;
	for(N=1,k=0;N<n;N<<=1)k++;
	for(i=0;i<N;i++)rev[i]=(rev[i>>1]>>1)|((i&1)<<(k-1));
	iN=pow(N,mod-2);
}
void ntt(int*a,int on){
	int i,j,k,t,w,wn;
	for(i=0;i<N;i++){
		if(i<rev[i])swap(a[i],a[rev[i]]);
	}
	for(i=2;i<=N;i<<=1){
		wn=pow(3,on==1?(mod-1)/i:mod-1-(mod-1)/i);
		for(j=0;j<N;j+=i){
			w=1;
			for(k=0;k<i>>1;k++){
				t=mul(a[i/2+j+k],w);
				a[i/2+j+k]=de(a[j+k],t);
				a[j+k]=ad(a[j+k],t);
				w=mul(w,wn);
			}
		}
	}
	if(on==-1){
		for(i=0;i<N;i++)a[i]=mul(a[i],iN);
	}
}
int ta[524288],tb[524288];
void conv(){
	ntt(ta,1);
	ntt(tb,1);
	for(int i=0;i<N;i++)ta[i]=mul(ta[i],tb[i]);
	ntt(ta,-1);
}
int fac[200010],rfac[200010];
char s[200010];
int a[200010],f[200010],g[200010],inv[400010];
void solve(int l,int r){
	if(l==r)return;
	int mid=(l+r)>>1,i;
	solve(l,mid);
	//f*f->g
	pre(r-l+mid-l+1);
	memset(ta,0,N<<2);
	memset(tb,0,N<<2);
	for(i=1;i<=r-l;i++)ta[i-1]=f[i];
	for(i=l;i<=mid;i++)tb[i-l]=f[i];
	conv();
	if(l>1){
		for(i=mid-l;i<r-l;i++)ta[i]=mul(ta[i],2);
	}
	for(i=1;i<=r-mid;i++)inc(g[i+mid],ta[i+mid-l-1]);
	//a*g->f
	memset(ta,0,N<<2);
	memset(tb,0,N<<2);
	for(i=0;i<r-l;i++)ta[i]=a[i];
	for(i=l;i<=mid;i++)tb[i-l]=g[i];
	conv();
	for(i=1;i<=r-mid;i++)inc(f[i+mid],mul(inv[2*(i+mid)],ta[i+mid-l-1]));
	solve(mid+1,r);
}
int main(){
	int n,i;
	scanf("%d%s",&n,s);
	fac[0]=1;
	for(i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
	rfac[n]=pow(fac[n],mod-2);
	for(i=n;i>0;i--)rfac[i-1]=mul(rfac[i],i);
	inv[1]=1;
	for(i=2;i<=2*n;i++)inv[i]=-mul(mod/i,inv[mod%i]);
	for(i=0;i<n;i++)a[i]=s[i]=='1'?rfac[i]:0;
	f[1]=1;
	solve(1,n);
	for(i=1;i<=n;i++)printf("%d\n",ad(mul(f[i],fac[i]),mod));
}

[UOJ50]链式反应的更多相关文章

  1. GOOD BYE OI

    大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...

  2. uoj50【UR#3】链式反应

    题解: 令$a(x)$为破坏死光的$EFG$,$f(x)$为方案的$EGF$:$f(x) = x + \int \  \frac{1}{2} f^2(x) a(x) \  dt$; 注意到$f(0)= ...

  3. 【UOJ#50】【UR #3】链式反应(分治FFT,动态规划)

    [UOJ#50][UR #3]链式反应(分治FFT,动态规划) 题面 UOJ 题解 首先把题目意思捋一捋,大概就是有\(n\)个节点的一棵树,父亲的编号大于儿子. 满足一个点的儿子有\(2+c\)个, ...

  4. nodejs,express链式反应

    链式反应--next() const myexpress = require('express'); const bodyparser = require('body-parser'); var se ...

  5. 【UR #3】链式反应

    http://uoj.ac/problem/50 %炮姐 好博客 树形结构 枚举根节点的儿子是哪两个 然后列出方程: 然后有EGF的影子! 倍增? 泰勒展开可以把未知数从函数里拿出来!并且变成1次项, ...

  6. Monte Carlo方法简介(转载)

    Monte Carlo方法简介(转载)       今天向大家介绍一下我现在主要做的这个东东. Monte Carlo方法又称为随机抽样技巧或统计实验方法,属于计算数学的一个分支,它是在上世纪四十年代 ...

  7. 关于转录组比对STAR软件使用

    参考文章:http://weibo.com/p/23041883f77c940102vbkd?sudaref=passport.weibo.com 软件连接:https://github.com/al ...

  8. [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据

    这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第七篇:为ASP.NET MVC应用程序 ...

  9. 《Xenogears》(异度装甲)隐含的原型与密码

    <Xenogears>(异度装甲)隐含的原型与密码 X 彩虹按:一种高次元的“生命体”,因“事故”被抓来当成“超能源”,其实那不只是“无限的能源”而已,“它”是有意志的!在我们眼里看来,这 ...

随机推荐

  1. 详解H5中的history单页面,手动实现单页面开发,细说h5单页面原理

    就目前来看,前端的单页面开发占了很大一部分,一方面无刷新的切换增强了体验,并且浏览器记录依然存在,前进后退都没问题,在之前我们通地址栏中的hash改变来触发onhashchange方法来实现单页面应用 ...

  2. Skip List(跳跃表)原理详解与实现【转】

    转自:http://dsqiu.iteye.com/blog/1705530 Skip List(跳跃表)原理详解与实现 本文内容框架: §1 Skip List 介绍 §2 Skip List 定义 ...

  3. 在Linux(CentOS)中安装.netcore SDK

    官方链接 :https://dotnet.microsoft.com/download/linux-package-manager/centos/sdk-current 可以直接根据官方链接,选择Li ...

  4. 域名 DNS命令——dig

    dig命令详解   1.查看域名的A记录          # dig yahoo.com; <<>> DiG 9.8.2rc1-RedHat-9.8.2-0.10.rc1.e ...

  5. IP地址及子网--四种IP广播地址

    国际规定:把所有的IP地址划分为 A,B,C,D,E. 类默认子网掩码:A类为 255.0.0.0; B类为 255.255.0.0; C类为 255.255.255.0.子网掩码是一个32位地址,用 ...

  6. Remove Duplicates from Sorted List II——简单的指针问题

    Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...

  7. MVC – 3.EF(Entity Framework)

    1.实体框架(EF)简介 与ADO.NET的关系 全称是ADO.NET Entity Framework,是微软开发的基于ADO.NET的ORM(Object/Relational Mapping)框 ...

  8. WMI技术介绍和应用——WMI概述

    https://blog.csdn.net/breaksoftware/article/details/8424317

  9. day5 常用模块json和pickle

    json 和 pickle json和pickle是用于字符串序列化和反序列化的过程,我们在存储和使用的时候,经常把列表存入文件,读取的时候我们还想以列表的形式读取.就需要使用json和pickle. ...

  10. win10家庭版和专业版远程桌面出现身份验证错误, 要求的函数不受支持。解决办法【亲测有效】

    1.解决 win10家庭中文版 远程连接:出现身份验证错误 要求的函数不受支持 Windows 5.10日更新后,远程连接出现失败. 提示: 出现身份验证错误.要求的函数不受支持 这可能是由于 Cre ...