BZOJ3684 大朋友和多叉树(多项式相关计算)
设$f(x)$为树的生成函数,即$x^i$的系数为根节点权值为$i$的树的个数。
不难得出$f(x)=\sum_{k\in D}f(x)^k+x$
我们要求这个多项式的第$n$项,由拉格朗日反演可得
$[x^n]f(x)=\frac1n[x^{n-1}](\frac x{g(x)})^n$
其中$[x^n]f(x)$表示$f(x)$的$n$次项系数。
$f(x)$是$g(x)$的复合逆,即$g(f(x))=x$
在本题中,$g(x)=x-\sum_{k\in D}x^k$
我们需要多项式求逆和多项式快速幂。
多项式求逆就不介绍了,多项式快速幂一种朴素的做法是倍增+NTT,复杂度是$O(n\log n\log k)$
有没有更快的做法呢?
观察到$f(x)^n=e^{n\ln(f(x))}$,所以我们只需要快速算$\ln(f(x))$及$e^{f(x)}$即可。
注意$f(x)$的常数项要为1,还好出题人良心保证了这一点。
Part 1:如何算$\ln(f(x))$?
设$g(x)=\ln(f(x))$,那么$g'(x)=\frac{f'(x)}{f(x)}$,所以$g(x)=\int\frac{f'(x)}{f(x)}$,时间复杂度$O(n\log n)$
Part 2:如何算$e^{f(x)}$?
还是考虑倍增,假设我已经求出$g_0(x)=e^{f(x)}(mod\;x^n)$,要求$g(x)=e^{f(x)}(mod\;x^{2n})$
根据泰勒展开,有$$0=h(g(x))=\sum_{i=0}^{\infty}\frac{h^{(i)}(g_0(x))}{i!}(g(x)-g_0(x))^i$$当$i>1$时,上式$mod\;x^{2n}$为$0$
所以$0=h(g_0(x))+h'(g_0(x))(g(x)-g_0(x))\;(mod\;x^{2n})$
即$g(x)=g_0(x)-\frac{h(g_0(x))}{h'(g_0(x))}(mod\;x^{2n})$
其中$h(g(x))=\ln(g(x))-f(x)$
所以$g(x)=g_0(x)-\frac{\ln(g_0(x))-f(x)}{\frac 1{g_0(x)}}=g_0(x)(1-\ln(g_0(x))+f(x))\;(mod\;x^{2n})$
时间复杂度$O(n\log n)$
#include <cstdio>
#include <cstring>
#include <algorithm>
#define pre m=n<<1; for(int i=0;i<m;i++) r[i]=(r[i>>1]>>1)|((i&1)<<l) typedef long long ll;
const int p=,N=;
int n,m,l,x,nn,f[N],g[N],t1[N],t2[N],t3[N],r[N],ni[N];
ll pw(ll a,int b) {ll r=; for(;b;b>>=,a=a*a%p) if(b&) r=r*a%p; return r;} void ntt(int *a,int n,int f) {
for(int i=;i<n;i++) if(r[i]>i) std::swap(a[i],a[r[i]]);
for(int i=;i<n;i<<=)
for(int j=,wn=pw(,((p-)/(i*)*f+p-)%(p-));j<n;j+=i<<)
for(int k=,w=;k<i;k++,w=(ll)w*wn%p) {
int x=a[j+k],y=(ll)a[j+k+i]*w%p;
a[j+k]=(x+y)%p,a[j+k+i]=(x-y+p)%p;
}
if(!~f) for(int i=;i<n;i++) a[i]=(ll)a[i]*ni[n]%p;
}
void inv(int *f,int *g,int *t,int n,int l) {
if(n==) {g[]=pw(f[],p-); return;}
inv(f,g,t,n>>,l-),memcpy(t,f,sizeof(int)*n),memset(t+n,,sizeof(int)*n),pre;ntt(t,m,),ntt(g,m,);
for(int i=;i<m;i++) g[i]=(ll)g[i]*(-(ll)t[i]*g[i]%p+p)%p;
ntt(g,m,-),memset(g+n,,sizeof(int)*n);
}
void ln(int *f,int *g,int *t,int n,int l) {
memset(t,,sizeof(int)*n*),inv(f,t,t1,n,l);
for(int i=;i+<n;i++) g[i]=(ll)f[i+]*(i+)%p;
pre;ntt(g,m,),ntt(t,m,);
for(int i=;i<m;i++) g[i]=(ll)g[i]*t[i]%p;
ntt(g,m,-);
for(int i=m-;i;i--) g[i]=(ll)g[i-]*ni[i]%p;
g[]=,memset(g+n,,sizeof(int)*n);
}
void ex(int *f,int *g,int *t,int n,int l) {
if(n==) {g[]=; return;}
ex(f,g,t,n>>,l-),memset(t,,sizeof(int)*n*),ln(g,t,t2,n,l);
for(int i=;i<n;i++) t[i]=(f[i]-t[i]+p)%p;
t[]=(t[]+)%p,pre;ntt(t,m,),ntt(g,m,);
for(int i=;i<m;i++) g[i]=(ll)g[i]*t[i]%p;
ntt(g,m,-),memset(g+n,,sizeof(int)*n);
} int main() {
scanf("%d%d",&n,&m),f[]++,ni[]=,nn=n;
for(int i=;i<=m;i++) scanf("%d",&x),f[x-]=p-;
for(m=n,n=,l=;n<=m;n<<=) l++;
for(int i=;i<=n*;i++) ni[i]=(ll)(p-p/i)*ni[p%i]%p;
inv(f,g,t1,n,l),memset(f,,sizeof f),ln(g,f,t2,n,l);
for(int i=;i<n;i++) f[i]=(ll)f[i]*nn%p;
memset(g,,sizeof g),ex(f,g,t3,n,l),printf("%lld",(ll)g[nn-]*ni[nn]%p);
return ;
}
BZOJ3684 大朋友和多叉树(多项式相关计算)的更多相关文章
- bzoj3684: 大朋友和多叉树(拉格朗日反演+多项式全家桶)
题面 传送门 题解 首先你得知道什么是拉格朗日反演->这里 我们列出树的个数的生成函数 \[T(x)=x+\prod_{i\in D}T^i(x)\] \[T(x)-\prod_{i\in D} ...
- [BZOJ3684]大朋友和多叉树
设答案为$f_s$,它的生成函数为$\begin{align*}F(x)=\sum\limits_{i=0}^\infty f_ix^i\end{align*}$,则我们有$\begin{align* ...
- BZOJ 3684: 大朋友和多叉树 [拉格朗日反演 多项式k次幂 生成函数]
3684: 大朋友和多叉树 题意: 求有n个叶子结点,非叶节点的孩子数量\(\in S, a \notin S\)的有根树个数,无标号,孩子有序. 鏼鏼鏼! 树的OGF:\(T(x) = \sum_{ ...
- BZOJ 3684 大朋友和多叉树
BZOJ 3684 大朋友和多叉树 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的: ...
- [BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树
题面 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为\(1\)的结点是叶子结 ...
- 【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演
这题一看就觉得是生成函数的题... 我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案. 根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$ ...
- 【BZOJ3684】大朋友和多叉树(拉格朗日反演)
题目链接 题意 求满足如下条件的多叉树个数: 1.每一个点的儿子个数在给定的集合 \(S\) 内 2.总的叶子节点树为 \(s\) 儿子之间有顺序关系,但节点是没有标号的. Sol 拉格朗日反演板子题 ...
- 【learning】多项式相关(求逆、开根、除法、取模)
(首先要%miskcoo,这位dalao写的博客(这里)实在是太强啦qwq大部分多项式相关的知识都是从这位dalao博客里面学的,下面这篇东西是自己对其博客学习后的一些总结和想法,大部分是按照其博客里 ...
- P2008 大朋友的数字
题目描述 有一批大朋友(年龄15岁以上),他们每人手上拿着一个数字,当然这个数字只有1位,也就是0到9之间.每个大朋友的分数为在他之前的最长不下降子序列中所有数之和.(这个序列必须以它作为结尾!)如有 ...
随机推荐
- RadioButton的图标改变大小(TextView也适用)
RadioButton的图标大小并没有相应的布局参数,本文通过自定义属性的方式自定义RadioButton,实现控制图片大小. 本文要点: 自定义属性的使用. 解决RadioButton文字上.下.左 ...
- nyoj Mod
Ocean用巧妙的方法得到了一个序列,该序列有N个元素,我们用数组a来记录(下标从0到N−1). Ocean定义f[i]=(((i%a[0])%a[1])%-)%a[N−1]. 现在Ocean会给出Q ...
- R语言基础1
----------------------------------R语言学习与科研应用,科研作图,数据统计挖掘分析,群:719954246-------------------------- 我们将 ...
- 07-TypeScript的For循环
在传统的JavaScript中,关于循环,可以有两种方式,一种是forEach,一种是for. forEach的用法如下: var sarr=[1,2,3,4]; sarr.desc="he ...
- JavaScript Cookie使用实例
# Session-Cookie // 利用Cookie防止在1分钟内多次提交: function SetCookie (name, value) { var Days = 30; var exp ...
- Python内置函数(8)——bool
英文文档: class bool([x]) Return a Boolean value, i.e. one of True or False. x is converted using the st ...
- JMeter入门(03)多台JMeter联合测试
一.配置各个节点 1.配置jmeter.properties # Remote Hosts - comma delimited#remote_hosts=localhost:1099,localhos ...
- ubuntu 虚拟机上的 django 服务,在外部Windows系统上无法访问
背景介绍 今天尝试着写了一个最简单的django 服务程序,使用虚拟机(Ubuntu16.02 LTS)上的浏览器访问程序没有问题.但是在物理机器上(win10 Home) 就出现错误 解决方法 在 ...
- ssh整合之四单独搭建struts的运行环境
1.导入struts的基本jar包 2.在web.xml中配置我们struts的核心控制器StrutsPrepareAndExecuteFilter <?xml version="1. ...
- show engine innodb status输出说明
参考链接 (https://dev.mysql.com/doc/refman/5.7/en/innodb-standard-monitor.html) 其中有这样一句: For a descripti ...