【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆
题目大意
考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots ,c_n\)。如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合\(\{c_1,c_2,\ldots ,c_n\}\)中,我们的小朋友就会将其称作神犇的。并且他认为,一棵带点权的树的权值,是其所有顶点权值的总和。
给出一个整数\(m\),你能对于任意的\(s(1\leq s\leq m)\)计算出权值为\(s\)的神犇二叉树的个数吗?
我们只需要知道答案关于\(998244353\)取模后的值。
\(n,m\leq 100000\)
题解
设\(a_i\)为\(c\)中有没有\(i\)这个权值。
设\(f_i\)为权值和为\(i\)的二叉树个数。
f_0&=1\\
f_i&=\sum_{0\leq j\leq i}a_j\sum_{k=0}^{i-j}f_kf_{i-j-k}\\
\end{align}
\]
设
A(x)&=\sum_{i\geq 0}a_ix^i\\
F(x)&=\sum_{i\geq 0}f_ix^i
\end{align}
\]
那么
F(x)&=F(x)^2A(x)+1\\
A(x)F(x)^2-F(x)+1&=0\\
\Delta&=1-4A(x)\\
F(x)&=\frac{1\pm\sqrt{1-4A(x)}}{2A(x)}\\
&=\frac{2}{1\pm\sqrt{1-4A(x)}}
\end{align}
\]
显然,当常数项有逆元的时候一个多项式才有逆元。而\(a_0=0\),所以只能取加号。
\]
直接多项式开根+多项式求逆。
时间复杂度:\(O(n\log n)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#include<utility>
#include<cmath>
#include<functional>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
void sort(int &a,int &b)
{
if(a>b)
swap(a,b);
}
void open(const char *s)
{
#ifndef ONLINE_JUDGE
char str[100];
sprintf(str,"%s.in",s);
freopen(str,"r",stdin);
sprintf(str,"%s.out",s);
freopen(str,"w",stdout);
#endif
}
int rd()
{
int s=0,c;
while((c=getchar())<'0'||c>'9');
do
{
s=s*10+c-'0';
}
while((c=getchar())>='0'&&c<='9');
return s;
}
int upmin(int &a,int b)
{
if(b<a)
{
a=b;
return 1;
}
return 0;
}
int upmax(int &a,int b)
{
if(b>a)
{
a=b;
return 1;
}
return 0;
}
const ll p=998244353;
const ll g=3;
ll fp(ll a,ll b)
{
ll s=1;
while(b)
{
if(b&1)
s=s*a%p;
a=a*a%p;
b>>=1;
}
return s;
}
const int maxn=600000;
ll inv[maxn];
namespace ntt
{
ll w1[maxn];
ll w2[maxn];
int rev[maxn];
int n;
void init(int m)
{
n=1;
while(n<m)
n<<=1;
int i;
for(i=2;i<=n;i<<=1)
{
w1[i]=fp(g,(p-1)/i);
w2[i]=fp(w1[i],p-2);
}
rev[0]=0;
for(i=1;i<n;i++)
rev[i]=(rev[i>>1]>>1)|((i&1)*(n>>1));
}
void ntt(int *a,int t)
{
int i,j,k;
int u,v,w,wn;
for(i=0;i<n;i++)
if(rev[i]<i)
swap(a[i],a[rev[i]]);
for(i=2;i<=n;i<<=1)
{
wn=(t==1?w1[i]:w2[i]);
for(j=0;j<n;j+=i)
{
w=1;
for(k=j;k<j+i/2;k++)
{
u=a[k];
v=1ll*a[k+i/2]*w%p;
a[k]=(u+v)%p;
a[k+i/2]=(u-v)%p;
w=1ll*w*wn%p;
}
}
}
if(t==-1)
{
u=fp(n,p-2);
for(i=0;i<n;i++)
a[i]=1ll*a[i]*u%p;
}
}
int x[maxn];
int y[maxn];
int z[maxn];
void copy_clear(int *a,int *b,int m)
{
int i;
for(i=0;i<m;i++)
a[i]=b[i];
for(i=m;i<n;i++)
a[i]=0;
}
void copy(int *a,int *b,int m)
{
int i;
for(i=0;i<m;i++)
a[i]=b[i];
}
void inverse(int *a,int *b,int m)
{
if(m==1)
{
b[0]=fp(a[0],p-2);
return;
}
inverse(a,b,m>>1);
init(m<<1);
copy_clear(x,a,m);
copy_clear(y,b,m>>1);
ntt(x,1);
ntt(y,1);
int i;
for(i=0;i<n;i++)
x[i]=y[i]*(2-1ll*x[i]*y[i]%p)%p;
ntt(x,-1);
copy(b,x,m);
}
int c[maxn],d[maxn];
void sqrt(int *a,int *b,int m)
{
if(m==1)
{
if(a[0]==1)
b[0]=1;
else if(a[0]==0)
b[0]=0;
else
//我也不会
;
return;
}
sqrt(a,b,m>>1);
// copy_clear(c,b,m>>1);
int i;
for(i=m;i<m<<1;i++)
b[i]=0;
inverse(b,d,m);
init(m<<1);
for(i=m;i<m<<1;i++)
b[i]=d[i]=0;
ll inv2=fp(2,p-2);
copy_clear(x,a,m);
ntt(x,1);
ntt(d,1);
for(i=0;i<n;i++)
x[i]=1ll*x[i]*d[i]%p;
ntt(x,-1);
for(i=0;i<m;i++)
b[i]=(1ll*(b[i]+x[i])%p*inv2)%p;
}
};
int a[maxn];
int b[maxn];
int main()
{
open("bzoj3625");
int n,m;
int i;
int x;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
{
scanf("%d",&x);
a[x]=1;
}
int k=1;
while(k<=m)
k<<=1;
for(i=0;i<k;i++)
a[i]=-4ll*a[i]%p;
a[0]=(a[0]+1)%p;
ntt::sqrt(a,b,k);
b[0]=(b[0]+1)%p;
ntt::inverse(b,a,k);
for(i=1;i<=m;i++)
{
a[i]=(a[i]*2ll%p+p)%p;
printf("%d\n",a[i]);
}
return 0;
}
【BZOJ3625】【CF438E】小朋友和二叉树 NTT 生成函数 多项式开根 多项式求逆的更多相关文章
- [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)
题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...
- [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)
[BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...
- CF438E The Child and Binary Tree(生成函数+多项式开根+多项式求逆)
传送门 可以……这很多项式开根模板……而且也完全不知道大佬们怎么把这题的式子推出来的…… 首先,这题需要多项式开根和多项式求逆.多项式求逆看这里->这里,这里讲一讲多项式开根 多项式开方:已知多 ...
- BZOJ3625 CF438E 小朋友与二叉树
心态崩了 不放传送门了 辣鸡bz 还是正经一点写一下题解= = 就是显然我们可以把权值写成生成函数形式g(0/1序列)来表示权值是否出现 然后f来表示总的方案数 可以列出 分别枚举左右子树和空树的情况 ...
- [BZOJ3625][CF438E]小朋友和二叉树
题面 Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots,c_n\).如果一棵带点权的有根二叉树满足其 ...
- BZOJ 3625:小朋友和二叉树 多项式开根+多项式求逆+生成函数
生成函数这个东西太好用了~ code: #include <bits/stdc++.h> #define ll long long #define setIO(s) freopen(s&q ...
- cf438E. The Child and Binary Tree(生成函数 多项式开根 多项式求逆)
题意 链接 Sol 生成函数博大精深Orz 我们设\(f(i)\)表示权值为\(i\)的二叉树数量,转移的时候可以枚举一下根节点 \(f(n) = \sum_{w \in C_1 \dots C_n} ...
- 洛谷P5205 【模板】多项式开根(多项式sqrt)
题意 题目链接 Sol 这个就很没意思了 求个ln,然后系数除以2,然后exp回去. #include<bits/stdc++.h> #define Pair pair<int, i ...
- BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根
生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...
随机推荐
- Web测试和App测试有什么区别
WEB测试和App测试从流程上来说,没有区别.都需要经历测试计划方案,用例设计,测试执行,缺陷管理,测试报告等相关活动.从技术上来说,WEB测试和APP测试其测试类型也基本相似,都需要进行功能测试.性 ...
- 543A - Writing Code(二维动态规划)
题意:现在要写m行代码,总共有n个文件,现在给出第i个文件每行会出现v[i]个bug,问你在bug少于b的条件下有多少种安排 分析:定义dp[i][j][k],i个文件,用了j行代码,有k个bug 状 ...
- R语言绘制直方图,
直方图: 核密度函数: 练习题目1: 绘制出15位同学体重的直方图和核密度估计图,并与正态分布的概率密度函数作对比 代码如下: > w <- c(75.0, 64.0, 47.4, 66. ...
- Dapper.NET
关于Dapper.NET的相关论述 年少时,为何不为自己的梦想去拼搏一次呢?纵使头破血流,也不悔有那年少轻狂.感慨很多,最近事情也很多,博客也很少更新了,毕竟每个人都需要为自己的生活去努力. 最近 ...
- 福州大学软件工程1816 | W班 第2次作业成绩排名
作业链接 词频统计基础功能 评分细则 本次个人项目分数由两部分组成(博客分满分40分+程序得分满分60分) 博客评分规则 在文章开头给出你们Fork仓库的Github项目地址.(1') 在开始实现程序 ...
- Linux (Redhat / Fedora / CentOS) 更改 hostname 的方式
Linux (Redhat / Fedora / CentOS) 更改 hostname 的方式 [蔡宗融個人網站]https://www.ichiayi.com/wiki/tech/linux_ho ...
- 初步了解HTTP
HTTP简介: HTTP:HyperText Transfer Protocol 超文本传输协议,是因特网上使用最为广泛的一种网络传输议,是用于从万维网(www :world wide web)服 ...
- [转帖]Docker 清理占用的磁盘空间
Docker(二十七)-Docker 清理占用的磁盘空间 https://www.cnblogs.com/zhuochong/p/10076599.html docker system docker ...
- macbookpro 以及 surface 的技术规格
macbookpro 13.3 英寸 (对角线) LED 背光显示屏 (采用 IPS 技术):初始分辨率 x ( ppi),支持数百万色彩 15.4 英寸 (对角线) LED 背光显示屏 (采用 IP ...
- java从request中获取GET和POST请求参数
URL和参数列表 一 获取请求方式 request.getMethod(); get和post都可用, 二 获取请求类型 request.getContentType(); get和post都可用,示 ...