这个题意说人话就是:一棵带标号的有根树,编号满足堆性质,根节点有$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. JS设计模式——2.初识接口

    什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...

  2. oracle01--单表查询

    1. 基本(基础)查询 1.1. 基本查询语法 基本查询是指最基本的select语句. [语法] [知识点]如何使用工具进行查询 在plsql developer中打开查询窗口(执行sql语句): 执 ...

  3. thinkphp博客项目纪录

    项目地址:http://files.cnblogs.com/files/wordblog/blog.zip

  4. 好消息! 不用再羡慕Python有jupyter 我R也有Notebook了【附演示视频】

    熟悉python的朋友可能知道jupyter notebook.它是一个Web应用程序,允许你创建和共享代码,方程,可视化和说明性文本文档.现在,我们可以在RStudio中实现R Notebook的功 ...

  5. linux下C语言实现的哈希链表【转】

    转自:http://blog.chinaunix.net/uid-28458801-id-4276934.html 操作系统:ubuntu10.04 前言:     在稍微大点的项目中,基本都会遇到算 ...

  6. Mysql 中 char 、varchar 、text的区别

    首先它们的存储方式和数据的检索方式都不一样.数据的检索效率是:char > varchar > text 空间占用方面,就要具体情况具体分析了. char:存储定长数据很方便,CHAR字段 ...

  7. selenium启动chrome模拟器模拟手机

    一.如果chrome选项里边有这个模拟设备(比如iPhone 6 Plus): 1.先启动Selenium Grid, 比如命令:java -jar selenium-server-standalon ...

  8. Linux shell中运行命令后加上字符“&”的作用(转)

    原文链接为:http://blog.sina.com.cn/s/blog_963453200102uya7.html & 放在启动参数后面表示设置此进程为后台进程 默认情况下,进程是前台进程, ...

  9. HDU 3018 Ant Trip (并查集求连通块数+欧拉回路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 题目大意:有n个点,m条边,人们希望走完所有的路,且每条道路只能走一遍.至少要将人们分成几组. ...

  10. POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))

    题目链接:http://poj.org/problem?id=1511 题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9.问你从起点到各个点以及从各个 ...