BZOJ 3684 大朋友和多叉树

Description

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

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

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

Input

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

第二行有\(m\)个互异的整数,\(d[1],d[2],…,d[m]\),为集合\(D\)中的元素。

Output

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

Sample Input

4 2

2 3

Sample Output

10


前置知识

\(\text{Lagrange}\)反演(金策的论文中有讲):

若两个没有常数项的函数\(f(x)\)和\(g(x)\)满足:

\[f(g(x))=x
\]

(也称这两个函数互为复合逆。)

我们就有:

\[[x^n]g(x)=\frac{1}{n}[w^{n-1}](\frac{w}{f(w)})^n
\]


设\(T(x)\)为答案的生成函数。

我们有:

\[T(x)=x+\sum_{i\in D}{T(x)}^i
\]

加上一个\(x\)是因为要考虑\(x\)为叶子的情况。

移项:

\[T(x)-\sum_{i\in D}{T(x)}^i=x
\]

设:

\[f(x)=x-\sum_{i\in D}x^i
\]

则:

\[f(T(x))=x\\
\Rightarrow [x^n]T(x)=\frac{1}{n}[w^{n-1}](\frac{w}{f(w)})^n
\]

\(\frac{w}{f(w)}\)上下约掉\(w\)后发现相当于将\(f(w)\)的每一项向左平移再求逆。

然后:

\[f(x)^k=\exp(k\ln(f(x)))
\]

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 100005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} const ll mod=950009857;
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
} ll NTT(ll *a,int d,int flag) {
static int rev[N<<2];
static int G=7;
int n=1<<d;
for(int i=0;i<n;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<d-1);
for(int i=0;i<n;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int s=1;s<=d;s++) {
int len=1<<s,mid=len>>1;
ll w=flag==1?ksm(G,(mod-1)/len):ksm(G,mod-1-(mod-1)/len);
for(int i=0;i<n;i+=len) {
ll t=1;
for(int j=0;j<mid;j++,t=t*w%mod) {
ll u=a[i+j],v=a[i+j+mid]*t%mod;
a[i+j]=(u+v)%mod;
a[i+j+mid]=(u-v+mod)%mod;
}
}
}
if(flag==-1) {
ll inv=ksm(n,mod-2);
for(int i=0;i<n;i++) a[i]=a[i]*inv%mod;
}
} void Inv(ll *inv,ll *a,int d) {
static ll A[N<<2];
if(!d) {
inv[0]=ksm(a[0],mod-2);
return ;
}
Inv(inv,a,d-1);
for(int i=0;i<1<<d;i++) A[i]=a[i];
for(int i=1<<d;i<1<<d+1;i++) A[i]=inv[i]=0;
NTT(A,d+1,1),NTT(inv,d+1,1);
for(int i=0;i<1<<d+1;i++) inv[i]=(2*inv[i]-inv[i]*inv[i]%mod*A[i]%mod+mod)%mod;
NTT(inv,d+1,-1);
for(int i=1<<d;i<1<<d+1;i++) inv[i]=0;
} void Der(ll *ans,ll *a,int d) {
int n=1<<d;
for(int i=0;i<n-1;i++) ans[i]=a[i+1]*(i+1)%mod;
ans[n-1]=0;
} void Int(ll *ans,ll *a,int d) {
int n=1<<d;
for(int i=n-1;i;i--) ans[i]=a[i-1]*ksm(i,mod-2)%mod;
ans[0]=0;
} void Ln(ll *ln,ll *a,int d) {
static ll inv[N<<2],der[N<<2];
for(int i=0;i<1<<d+1;i++) inv[i]=der[i]=0;
Inv(inv,a,d);Der(der,a,d);
NTT(inv,d+1,1),NTT(der,d+1,1);
for(int i=0;i<1<<d+1;i++) ln[i]=inv[i]*der[i]%mod;
NTT(ln,d+1,-1);
Int(ln,ln,d);
for(int i=1<<d;i<1<<d+1;i++) ln[i]=0;
} void Exp(ll *ex,ll *a,int d) {
static ll A[N<<2],ln[N<<2];
if(d==0) {
ex[0]=1;
return ;
}
Exp(ex,a,d-1);
for(int i=0;i<1<<d+1;i++) A[i]=ln[i]=0;
for(int i=0;i<1<<d;i++) A[i]=a[i];
Ln(ln,ex,d);
NTT(ln,d+1,1),NTT(A,d+1,1);
NTT(ex,d+1,1);
for(int i=0;i<1<<d+1;i++) ex[i]=ex[i]*(1-ln[i]+A[i]+mod)%mod;
NTT(ex,d+1,-1);
for(int i=1<<d;i<1<<d+1;i++) ex[i]=0;
} ll A[N<<2],inv[N<<2],ln[N<<2],ex[N<<2];
ll f[N<<2];
int n,m; int main() {
n=Get(),m=Get();
int d=ceil(log2(n+1));
for(int i=1;i<=m;i++) {
int a=Get();
f[a-1]=mod-1;
}
f[0]=1;
Inv(inv,f,d);
Ln(ln,inv,d);
for(int i=0;i<1<<d;i++) ln[i]=ln[i]*n%mod;
Exp(ex,ln,d);
cout<<ex[n-1]*ksm(n,mod-2)%mod;
return 0;
}

BZOJ 3684 大朋友和多叉树的更多相关文章

  1. BZOJ 3684: 大朋友和多叉树 [拉格朗日反演 多项式k次幂 生成函数]

    3684: 大朋友和多叉树 题意: 求有n个叶子结点,非叶节点的孩子数量\(\in S, a \notin S\)的有根树个数,无标号,孩子有序. 鏼鏼鏼! 树的OGF:\(T(x) = \sum_{ ...

  2. [BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树

    题面 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为\(1\)的结点是叶子结 ...

  3. 【BZOJ3684】大朋友和多叉树(拉格朗日反演)

    题目链接 题意 求满足如下条件的多叉树个数: 1.每一个点的儿子个数在给定的集合 \(S\) 内 2.总的叶子节点树为 \(s\) 儿子之间有顺序关系,但节点是没有标号的. Sol 拉格朗日反演板子题 ...

  4. [BZOJ3684]大朋友和多叉树

    设答案为$f_s$,它的生成函数为$\begin{align*}F(x)=\sum\limits_{i=0}^\infty f_ix^i\end{align*}$,则我们有$\begin{align* ...

  5. BZOJ3684 大朋友和多叉树(多项式相关计算)

    设$f(x)$为树的生成函数,即$x^i$的系数为根节点权值为$i$的树的个数.不难得出$f(x)=\sum_{k\in D}f(x)^k+x$我们要求这个多项式的第$n$项,由拉格朗日反演可得$[x ...

  6. 【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演

    这题一看就觉得是生成函数的题... 我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案. 根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$ ...

  7. bzoj3684: 大朋友和多叉树(拉格朗日反演+多项式全家桶)

    题面 传送门 题解 首先你得知道什么是拉格朗日反演->这里 我们列出树的个数的生成函数 \[T(x)=x+\prod_{i\in D}T^i(x)\] \[T(x)-\prod_{i\in D} ...

  8. [BZOJ 3652]大新闻

    [BZOJ 3652] 大新闻 题意 随机从 \([0,n)\) 中选取一个整数 \(x\), 并从 \([0,n)\) 中再选取一个整数 \(y\). 有 \(p\) 的概率选取一个能令 \(x\o ...

  9. P2008 大朋友的数字

    题目描述 有一批大朋友(年龄15岁以上),他们每人手上拿着一个数字,当然这个数字只有1位,也就是0到9之间.每个大朋友的分数为在他之前的最长不下降子序列中所有数之和.(这个序列必须以它作为结尾!)如有 ...

随机推荐

  1. Python爬虫入门教程 14-100 All IT eBooks多线程爬取

    All IT eBooks多线程爬取-写在前面 对一个爬虫爱好者来说,或多或少都有这么一点点的收集癖 ~ 发现好的图片,发现好的书籍,发现各种能存放在电脑上的东西,都喜欢把它批量的爬取下来. 然后放着 ...

  2. 【Python3爬虫】第一个Scrapy项目

    Python版本:3.5    IDE:Pycharm 今天跟着网上的教程做了第一个Scrapy项目,遇到了很多问题,花了很多时间终于解决了== 一.Scrapy终端(scrapy shell) Sc ...

  3. JDBC 异常简介 jDBC简介(六)

    SQL 异常简介 对于数据库的操作访问,必然也很可能抛出异常. JDBC中定义了SQLException,用于描述数据库相关操作中可能出现的异常情况. java.sql.SQLException    ...

  4. 痞子衡嵌入式:ARM Cortex-M文件那些事(4)- 可重定向文件(.o/.a)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家讲的是嵌入式开发里的relocatable文件(object, library). 前三节课里,痞子衡都是在给大家介绍嵌入式开发中的input文 ...

  5. 基于React-Native0.55.4的语音识别项目全栈方案

    移动端的API能力验证方案与PC端不一样!不一样!!不一样!!! 即使需要使用的API都存在,也不一定能用,这一点和PC端是有很大区别的,国内的手机系统虽然都是基于Android,但几乎都会经过各大厂 ...

  6. 第2章 术语 - Identity Server 4 中文文档(v1.0.0)

    规范.文档和对象模型等都使用特定的术语来表述. 2.1 IdentityServer IdentityServer是OpenID Connect提供程序 - 它实现OpenID Connect和OAu ...

  7. Java开发笔记(十六)非此即彼的条件分支

    前面花了大量篇幅介绍布尔类型及相应的关系运算和逻辑运算,那可不仅仅是为了求真值或假值,更是为了通过布尔值控制流程的走向.在现实生活中,常常需要在岔路口抉择走去何方,往南还是往北,向东还是向西?在Jav ...

  8. 高效使用VSCode的9点建议

    在开源 IDE 市场,最近几年 Visual Studio Code(简称 VSCode)越来越流行.自从 2015 年对外发布后,根据 2018 年 Stack Overflow 的调查报告,有 3 ...

  9. linux下sophos,clamav+clamtk杀毒软件

    以deepin为例 avast for linux sophos for linux comodo for linux 目前能够在官网找到. 先说clamav clamav 听说很活跃,clamav是 ...

  10. Idea软件中隐藏忽略.idea,.iml等文件

    参考链接,https://blog.csdn.net/fanrenxiang/article/details/80533950 ignore files and folders;增加隐藏的文件类型: