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. Javascript 链式操作以及流程控制

    春节过后,感觉过年吃的油腻的食品转化的脂肪都长到 脑子去了. 根本转不动啊 上班第一天 实在是写不动代码了, 顺手打开多天为看的 收件箱,查看查看邮件,看看春节期间 风云变幻的前端圈又有哪些大事发生. ...

  2. nginx~linux下的部署

    一些概念     Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄 ...

  3. Python包的导入说明

    import 模块 from 包 import 模块 上面的代码有什么区别呢? from 模块 import * 这种导入想象与把模块里面的代码都复制到当前模块中(也就是该语句所在位置),这时候你可以 ...

  4. C语言实现循环队列的初始化&进队&出队&读取队头元素&判空-2

    /*顺序表实现队列的一系列操作(设置flag标志不损失数组空间)*/ #include<stdio.h> #include<stdlib.h> #define Queue_Si ...

  5. 解决Mysql错误:ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (111)

    需要重启服务器:sudo /etc/init.d/mysql restart

  6. 超详细“零”基础kafka入门篇

    1.认识kafka 1.1 kafka简介 Kafka 是一个分布式流媒体平台 kafka官网:http://kafka.apache.org/ (1)流媒体平台有三个关键功能: 发布和订阅记录流,类 ...

  7. Python四步实现决策树ID3算法,参考机器学习实战

    一.编写计算历史数据的经验熵函数 from math import log def calcShannonEnt(dataSet): numEntries = len(dataSet) labelCo ...

  8. Docker容器监控(十)--技术流ken

    docker自带的监控命令 docker自带了三个监控命令即ps, top, stats ps docker ps 可以帮助我们很快的了解当前正在运行的容器 -a:会显示已经停掉的容器 [root@h ...

  9. 《C#并发编程经典实例》学习笔记—2.4 等待一组任务完成

    问题 执行几个任务,等待它们全部完成. 使用场景 几个独立任务需要同时进行 UI界面加载多个模块,并发请求 解决方案 Task.WhenAll 传入若干任务,当所有任务完成时,返回一个完成的任务. 重 ...

  10. JSON 数据转换

    JSON概述      JSON(Java Script Object Notation)JS对象符号,通常JSON和XML是二选一的,JSON的数据格式很类似于JavaScript的对象 { &qu ...