[UOJ50]链式反应
这个题意说人话就是:一棵带标号的有根树,编号满足堆性质,根节点有$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]链式反应的更多相关文章
- GOOD BYE OI
大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...
- uoj50【UR#3】链式反应
题解: 令$a(x)$为破坏死光的$EFG$,$f(x)$为方案的$EGF$:$f(x) = x + \int \ \frac{1}{2} f^2(x) a(x) \ dt$; 注意到$f(0)= ...
- 【UOJ#50】【UR #3】链式反应(分治FFT,动态规划)
[UOJ#50][UR #3]链式反应(分治FFT,动态规划) 题面 UOJ 题解 首先把题目意思捋一捋,大概就是有\(n\)个节点的一棵树,父亲的编号大于儿子. 满足一个点的儿子有\(2+c\)个, ...
- nodejs,express链式反应
链式反应--next() const myexpress = require('express'); const bodyparser = require('body-parser'); var se ...
- 【UR #3】链式反应
http://uoj.ac/problem/50 %炮姐 好博客 树形结构 枚举根节点的儿子是哪两个 然后列出方程: 然后有EGF的影子! 倍增? 泰勒展开可以把未知数从函数里拿出来!并且变成1次项, ...
- Monte Carlo方法简介(转载)
Monte Carlo方法简介(转载) 今天向大家介绍一下我现在主要做的这个东东. Monte Carlo方法又称为随机抽样技巧或统计实验方法,属于计算数学的一个分支,它是在上世纪四十年代 ...
- 关于转录组比对STAR软件使用
参考文章:http://weibo.com/p/23041883f77c940102vbkd?sudaref=passport.weibo.com 软件连接:https://github.com/al ...
- [渣译文] 使用 MVC 5 的 EF6 Code First 入门 系列:为ASP.NET MVC应用程序读取相关数据
这是微软官方教程Getting Started with Entity Framework 6 Code First using MVC 5 系列的翻译,这里是第七篇:为ASP.NET MVC应用程序 ...
- 《Xenogears》(异度装甲)隐含的原型与密码
<Xenogears>(异度装甲)隐含的原型与密码 X 彩虹按:一种高次元的“生命体”,因“事故”被抓来当成“超能源”,其实那不只是“无限的能源”而已,“它”是有意志的!在我们眼里看来,这 ...
随机推荐
- JS设计模式——2.初识接口
什么是接口 接口提供了一种用以说明一个对象应该具有哪些方法的手段. 接口之利 1.接口具有自我描述性从而促进代码的重用 2.接口有助于稳定不同中的类之间的通信方式 3.测试和调试也变得更轻松 接口之弊 ...
- oracle01--单表查询
1. 基本(基础)查询 1.1. 基本查询语法 基本查询是指最基本的select语句. [语法] [知识点]如何使用工具进行查询 在plsql developer中打开查询窗口(执行sql语句): 执 ...
- thinkphp博客项目纪录
项目地址:http://files.cnblogs.com/files/wordblog/blog.zip
- 好消息! 不用再羡慕Python有jupyter 我R也有Notebook了【附演示视频】
熟悉python的朋友可能知道jupyter notebook.它是一个Web应用程序,允许你创建和共享代码,方程,可视化和说明性文本文档.现在,我们可以在RStudio中实现R Notebook的功 ...
- linux下C语言实现的哈希链表【转】
转自:http://blog.chinaunix.net/uid-28458801-id-4276934.html 操作系统:ubuntu10.04 前言: 在稍微大点的项目中,基本都会遇到算 ...
- Mysql 中 char 、varchar 、text的区别
首先它们的存储方式和数据的检索方式都不一样.数据的检索效率是:char > varchar > text 空间占用方面,就要具体情况具体分析了. char:存储定长数据很方便,CHAR字段 ...
- selenium启动chrome模拟器模拟手机
一.如果chrome选项里边有这个模拟设备(比如iPhone 6 Plus): 1.先启动Selenium Grid, 比如命令:java -jar selenium-server-standalon ...
- Linux shell中运行命令后加上字符“&”的作用(转)
原文链接为:http://blog.sina.com.cn/s/blog_963453200102uya7.html & 放在启动参数后面表示设置此进程为后台进程 默认情况下,进程是前台进程, ...
- HDU 3018 Ant Trip (并查集求连通块数+欧拉回路)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 题目大意:有n个点,m条边,人们希望走完所有的路,且每条道路只能走一遍.至少要将人们分成几组. ...
- POJ 1511 Invitation Cards(Dijkstra(优先队列)+SPFA(邻接表优化))
题目链接:http://poj.org/problem?id=1511 题目大意:给你n个点,m条边(1<=n<=m<=1e6),每条边长度不超过1e9.问你从起点到各个点以及从各个 ...