博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树
阅读量:5167 次
发布时间:2019-06-13

本文共 2766 字,大约阅读时间需要 9 分钟。

题面

Description

我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树。对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为\(1\)的结点是叶子结点;对于任一点权大于\(1\)的结点\(u\)\(u\)的孩子数目\(deg_u\)属于集合\(D\),且\(u\)的点权等于这些孩子结点的点权之和。

给出一个整数\(s\),你能求出根节点权值为\(s\)的神犇多叉树的个数吗?请参照样例以更好的理解什么样的两棵多叉树会被视为不同的。

我们只需要知道答案关于\(950009857\)\(453\times2^{21}+1\),一个质数)取模后的值。

Input

第一行有\(2\)个整数\(s,m\)

第二行有\(m\)个互异的整数,\(d_1,d_2,\ldots,d_m\),为集合\(D\)中的元素。

Output

输出一行仅一个整数,表示答案模\(950009857\)的值。

Sample Input

4 2

2 3

Sample Output

10

HINT

70

\(1\le m\le s\le10^5,2\le d_i\le s\),有\(3\)组小数据和\(3\)组大数据。

分析

首先,我们设\(v_i\)为集合\(D\)中是否有\(i\)这个元素,有则为\(1\),无则为\(0\)\[v_i=\sum_{k=1}^{m}[d_k=i]\]

我们令\(V(x)\)\(v_i\)的生成函数:\[V(x)=\sum_{k=0}^\infty v_i x^k\]

我们再设\(f_i\)为根节点权值为\(i\)的神犇多叉树的数量。

首先,显然有\(f_0=0\);而当\(i=1\)即叶子节点时,有\(f_1=1\)

而在\(i>1\)时,我们枚举根节点的儿子节点数量,在枚举各个叶子节点的权值,根据乘法原理得到递归式:\[f_i=\sum_{k=0}^{i-1}v_k\sum_{s_1+s_2+\cdots+s_k=i}\;\;\prod_{j=1}^k f_j\]

我们发现后面这个是一个\(k\)重卷积。那么我们令\(F(x)\)\(f_i\)的生成函数:\[F(x)=\sum_{k=0}^\infty f_k x^k\]

那么我们根据递归式再加上特殊情况时的值,可以得到:\[F(x)=\sum_{k=0}^\infty v_k F(x)^k+x\]

那么我们发现这就是\(V(x)\)的形式。那么我们就得到:\[F(x)=V(F(x))+x\]

\[F(x)-V(F(x))=x\]

只要我们令\(G(x)=x-V(x)\),就可以构造出一个拉格朗日反演的形式:\[G(F(x))=x\]

那么我们作反演就得到:\[[x^n]F(x)=\frac{1}{n}[x^{n-1}]\left(\frac{x}{G(x)}\right)^n\]

即:\[f_s=\frac{1}{s}[x^{s-1}]\left(\frac{x}{G(x)}\right)^s\]

注意到我们可以\(x\)\(G(x)\)约掉一个\(x\),则我们令:\[H(x)=\sum_{k=0}^\infty v_{k+1} x^k=\frac{C(x)}{x}\]

则有:\[f_s=\frac{1}{s}[x^{s-1}]\left(\frac{1}{1-H(x)}\right)^n\]

我们直接多项式求逆+多项式求幂就可以解决了。

关于拉格朗日反演、多项式的操作,详见我的这篇博客:

代码

#include
#include
#include
using namespace std;typedef long long ll;const ll p=950009857,g=7;int n,nn,s,m,r[262145];ll inv[262145],c[262145],gn[2][262145],ans;inline ll pow(ll a,int b){ ll ans=1; while(b){ if(b&1)ans=ans*a%p; a=a*a%p; b>>=1; } return ans;}inline ll add(ll a,ll b){return a+b>p?a+b-p:a+b;}inline ll cut(ll a,ll b){return a-b<0?a-b+p:a-b;}void init(){ for(n=1;n<=s;n<<=1); nn=n; gn[0][0]=gn[1][0]=1; gn[0][1]=pow(g,(p-1)/(n<<1)); gn[1][1]=pow(gn[0][1],p-2); for(int i=2;i<(n<<1);i++){gn[0][i]=gn[0][i-1]*gn[0][1]%p;gn[1][i]=gn[1][i-1]*gn[1][1]%p;} inv[1]=1; for(int i=2;i<=(n<<1);i++)inv[i]=inv[p%i]*(p-p/i)%p;}void NTT(ll c[],int n,int tp=1){ for(int i=0;i
>1]>>1)|((i&1)*(n>>1)); if(i
>1);i<(k<<1);i++)t[i]=0; NTT(tma,k<<1); NTT(t,k<<1); for(int i=0;i<(k<<1);i++)t[i]=cut(add(t[i],t[i]),t[i]*t[i]%p*tma[i]%p); INTT(t,k<<1); } memcpy(c,t,sizeof(ll)*n);}void derivative(ll c[],int n=n){for(int i=0;i
=1;i--)c[i]=c[i-1]*inv[i]%p;c[0]=0;}void ln(ll c[],int n=n){ static ll t[262145]; for(int i=0;i<(n<<1);i++)t[i]=(i

转载于:https://www.cnblogs.com/eztjy/p/9382357.html

你可能感兴趣的文章
UVa 111 History Grading (最长公共子序列)
查看>>
linux基本命令
查看>>
Oracle插入日期格式出现 ORA-01843: not a valid month的解决办法
查看>>
HashSet的实现原理
查看>>
Java HashMap 分析之四:查找和内存使用
查看>>
《与熊共舞》——软件项目风险管理
查看>>
Linux system函数详解
查看>>
spring-boot启动信息中non-fatal error
查看>>
ubuntu14.04 Hadoop单机开发环境搭建MapReduce项目
查看>>
论文笔记:Deformable ConvNets v2: More Deformable, Better Results
查看>>
开通博客
查看>>
day03_04 文件后缀及系统环境变量
查看>>
JAVASCRIPT和JSP计算闰年
查看>>
OracleDBConsole启动不了
查看>>
PhoneGap工具Cloud9 IDE介绍以及使用方法
查看>>
HTML5 File 对象
查看>>
顺序表和链式表总结
查看>>
vc6.0中的dsp,dsw,ncb,opt,clw,plg,aps等文件的简单说明
查看>>
深入浅出SharePoint2013——安装SharePoint2013
查看>>
回校前的流水账
查看>>