参考:https://www.cnblogs.com/2016gdgzoi509/p/8999460.html

列出生成函数方程,g(x)是价值x的个数

\[f(x)=g(x)*f^2(x)+1
\]

+1是f[0]=1

根据公式解出

\[f(x)=\frac{1+(-)\sqrt{1-4*g(x)}}{2*g(x)}
\]

舍去+的答案,分式上下同乘\( 1-\sqrt{1-4*g(x)} \)

\[f(x)=\frac{2}{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+多项式开根求逆】的更多相关文章

  1. BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根

    生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...

  2. BZOJ 3625: [Codeforces Round #250]小朋友和二叉树

    3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 13 ...

  3. [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆

    https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...

  4. BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)

    设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...

  5. [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)

    题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...

  6. BZOJ3625: [Codeforces Round #250]小朋友和二叉树

    Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树.考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{ ...

  7. [Codeforces Round #250]小朋友和二叉树

    题目描述: bzoj luogu 题解: 生成函数ntt. 显然这种二叉树应该暴力薅掉树根然后分裂成两棵子树. 所以$f(x)= \sum_{i \in c} \sum _{j=0}^{x-c} f( ...

  8. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

  9. Codeforces Round #250 (Div. 1)E. The Child and Binary Tree

    题意:有一个集合,求有多少形态不同的二叉树满足每个点的权值都属于这个集合并且总点权等于i 题解:先用生成函数搞出来\(f(x)=f(x)^2*c(x)+1\) 然后转化一下变成\(f(x)=\frac ...

随机推荐

  1. python实现QQ机器人(自己主动登录,获取群消息,发送群消息)

    一次偶然的机会我看见了一个群里的一个QQ号总是依据你所发的消息自己主动回复,当时非常感觉到奇妙.我知道能够模拟登录站点,没想到居然也能模拟登录QQ,首先自己想到的就是怎样实现模拟登录PC端的QQ, 開 ...

  2. binary-tree-preorder-traversal——前序遍历

    Given a binary tree, return the preorder traversal of its nodes' values. For example:Given binary tr ...

  3. 【linux驱动分析】之dm9000驱动分析(三):sk_buff结构分析

    [linux驱动分析]之dm9000驱动分析(一):dm9000原理及硬件分析 [linux驱动分析]之dm9000驱动分析(二):定义在板文件里的资源和设备以及几个宏 [linux驱动分析]之dm9 ...

  4. ORACLE 8i 遇到报错:ORA-01631: max # extents (505) reached in table

    近期在客户的一个8i生产库上使用statspack.发现alert中有报错: Mon Jun 16 13:17:52 2014 Errors in file /oracle/8.1.7/admin/p ...

  5. java:[1,0] illegal character: \65279 问题

    部署项目的时候报下面错误 [java] view plaincopyprint? java:[1,0] illegal character: \65279 java:[1,10] class, int ...

  6. 软件版本号(BETA、RC、ALPHA、Release、GA等)

    Alpha:        Alpha是内部测试版,一般不向外部发布,会有很多Bug.除非你也是测试人员,否则不建议使用.是希腊字母的第一位,表示最初级的版本,alpha 就是α,beta 就是β , ...

  7. querying rpm database

    Call dbMatch on a transaction set to create a match iterator. As with the C API, a match iterator al ...

  8. 将线上服务器生成的日志信息实时导入kafka,采用agent和collector分层传输,app的数据通过thrift传给agent,agent通过avro sink将数据发给collector,collector将数据汇集后,发送给kafka

    记flume部署过程中遇到的问题以及解决方法(持续更新) - CSDN博客 https://blog.csdn.net/lijinqi1987/article/details/77449889 现将调 ...

  9. [转]GPS NEMA 0183协议

    一. NMEA0183标准语句(GPS常用语句) $GPGGA例:$GPGGA,092204.999,4250.5589,S,14718.5084,E,1,04,24.4,19.7,M,,,,0000 ...

  10. pageHelper没有分页效果的问题

    配置完全都没有问题 springboot pagehelper分页怎么都不管用 而且所有的信息记录全部都查出来了 解决方法: PageHelper.startPage(pageNum,pageSize ...