bzoj 3625: [Codeforces Round #250]小朋友和二叉树【NTT+多项式开根求逆】
参考:https://www.cnblogs.com/2016gdgzoi509/p/8999460.html
列出生成函数方程,g(x)是价值x的个数
\]
+1是f[0]=1
根据公式解出
\]
舍去+的答案,分式上下同乘\( 1-\sqrt{1-4*g(x)} \)
\]
然后套多项式开跟和求逆的板子即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=500005,mod=998244353,inv2=499122177;
int n,m,bt,lm,re[N],a[N],b[N],c[N],t[N];//,aa[N],bb[N],cc[N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
int ksm(int a,int b)
{
int r=1;
while(b)
{
if(b&1)
r=1ll*r*a%mod;
a=1ll*a*a%mod;
b>>=1;
}
return r;
}
void dft(int a[],int f,int lm)
{
// for(int i=0;i<lm;i++)
// cerr<<a[i]<<" ";cerr<<endl;
// bt=log2(lm);//cerr<<" "<<lm<<" "<<bt<<endl;
// for(int i=0;i<lm;i++)
// re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
for(int i=0;i<lm;i++)
if(i<re[i])
swap(a[i],a[re[i]]);
for(int i=1;i<lm;i<<=1)
{
int wi=ksm(3,(mod-1)/(i*2));
if(f==-1)
wi=ksm(wi,mod-2);
for(int k=0;k<lm;k+=(i<<1))
{
int w=1,x,y;
for(int j=0;j<i;j++)
{
x=a[j+k],y=1ll*w*a[i+j+k]%mod;
a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
w=1ll*w*wi%mod;
}
}
}
if(f==-1)
{
int ni=ksm(lm,mod-2);
for(int i=0;i<lm;i++)
a[i]=1ll*a[i]*ni%mod;
}
// for(int i=0;i<lm;i++)
// cerr<<a[i]<<" ";cerr<<endl<<endl;;
}
void qiuni(int len)
{
if(len==1)
{
c[0]=ksm(b[0],mod-2);
return;
}
qiuni(len>>1);
memcpy(t,b,sizeof(int)*len);
memset(t+len,0,sizeof(int)*len);
int bt=-1,lm=1;
while(lm<len<<1)
lm<<=1,bt++;
for(int i=0;i<lm;i++)
re[i]=(re[i>>1]>>1)|((i&1)<<bt);
dft(t,1,lm);
dft(c,1,lm);
for(int i=0;i<lm;i++)
c[i]=1ll*c[i]*(2-1ll*t[i]*c[i]%mod+mod)%mod;
dft(c,-1,lm);
memset(c+len,0,sizeof(int)*len);
}
void kaigen(int len)
{
if(len==1)
{
b[0]=1;
return;
}
kaigen(len>>1);
memset(c,0,sizeof(int)*len);
qiuni(len);
memcpy(t,a,sizeof(int)*len);
memset(t+len,0,sizeof(int)*len);
int bt=-1,lm=1;
while(lm<len<<1)
lm<<=1,bt++;
for(int i=0;i<lm;i++)
re[i]=(re[i>>1]>>1)|((i&1)<<bt);
dft(t,1,lm);
dft(b,1,lm);
dft(c,1,lm);
for(int i=0;i<len*2;i++)
b[i]=1ll*(1ll*b[i]*b[i]+t[i])%mod*c[i]%mod*inv2%mod;
dft(b,-1,lm);
memset(b+len,0,sizeof(int)*len);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
{
int x=read();
a[x]++;
}
for(int i=1;i<=m;i++)
a[i]=(-a[i]*4+mod)%mod;
for(bt=1;(1<<bt)<=m;bt++);
lm=(1<<bt);
for(int i=0;i<lm;i++)
if(a[i])
a[i]=mod-4;
a[0]++;
kaigen(lm);
// for(int i=0;i<n;i++)
// cerr<<a[i]<<" "<<b[i]<<" "<<c[i]<<endl;
b[0]=(b[0]+1)%mod;
memset(c,0,sizeof(c));
qiuni(lm);
for(int i=1;i<=m;i++)
printf("%d\n",c[i]*2%mod);
return 0;
}
bzoj 3625: [Codeforces Round #250]小朋友和二叉树【NTT+多项式开根求逆】的更多相关文章
- BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根
生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...
- BZOJ 3625: [Codeforces Round #250]小朋友和二叉树
3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 13 ...
- [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆
https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...
- BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)
设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...
- [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)
题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...
- BZOJ3625: [Codeforces Round #250]小朋友和二叉树
Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树.考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{ ...
- [Codeforces Round #250]小朋友和二叉树
题目描述: bzoj luogu 题解: 生成函数ntt. 显然这种二叉树应该暴力薅掉树根然后分裂成两棵子树. 所以$f(x)= \sum_{i \in c} \sum _{j=0}^{x-c} f( ...
- [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)
[BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...
- Codeforces Round #250 (Div. 1)E. The Child and Binary Tree
题意:有一个集合,求有多少形态不同的二叉树满足每个点的权值都属于这个集合并且总点权等于i 题解:先用生成函数搞出来\(f(x)=f(x)^2*c(x)+1\) 然后转化一下变成\(f(x)=\frac ...
随机推荐
- 使用RPi-Monitor监控、统计Guitar的运行状态
前言 之前发在ickey社区上的一系列文章: 犹抱琵琶半遮面,无人知是荔枝来--unboxing & interview 一.二.三 葡萄美酒夜光杯,巧妇难为无米炊--资料与社区 一支穿云箭, ...
- 用 centrifugo 搭建 消息推送服务器 docker + rancher 搭建
关于消息推送服务器 目前有很多第三方的开放成熟的推送服务.鉴于项目需要 我们项目需要自己搭建 自己的推送服务. 我们的推送应用场景 聊天消息 项目内部消息提醒 移动设备接受消息 应用到的相关软件工具知 ...
- Android4.42-Setting源代码分析之蓝牙模块Bluetooth(下)
接着上一篇Android4.42-Settings源代码分析之蓝牙模块Bluetooth(上) 继续蓝牙模块源代码的研究 THREE.蓝牙模块功能实现 switch的分析以及本机蓝牙重命名和可见性的分 ...
- 安卓自己定义View进阶-Canvas之绘制基本形状
Canvas之绘制基本形状 作者微博: @GcsSloop [本系列相关文章] 在上一篇自己定义View分类与流程中我们了解自己定义View相关的基本知识,只是,这些东西依然还是理论,并不能拿来(zh ...
- ubuntu 的权限和目录
/ : 根目录 /bin 和 /sbin中放置的是可执行文件 /etc 里面放的是配置文件 /boot 引导 /mnt 是挂载目录 /home 主目录 /dev 设备 /usr li ...
- uva 1567 - A simple stone game(K倍动态减法游戏)
option=com_onlinejudge&Itemid=8&page=show_problem&problem=4342">题目链接:uva 1567 - ...
- Page Design for Sexable Forum
Design Demo 1. Home of Sexable Forum 1.1 home page not logined. 1,2 home page logined. 2. Pages wit ...
- ViewPagerTransforms
https://github.com/eltld/ViewPagerTransforms
- 利用python暴力破解ssh
# -*- coding:utf-8 -*- #python 2.7 import optparse,sys,threading import pexpect PROMPT = ['#','>' ...
- 修改flash builder注释里的@author
在flash builder里,按Ctrl+Shift+D可以很方便在添加AsDoc注释.可是有些生成的@author是系统的用户名(如:administor),怎么修改这个为自己的名字呢? Step ...