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之间.每个大朋友的分数为在他之前的最长不下降子序列中所有数之和.(这个序列必须以它作为结尾!)如有 ...
随机推荐
- 【iOS】Swift GCD-下
欢迎来到本GCD教程的第二同时也是最终部分! 在第一部分中,你学到了并发,线程以及GCD的工作原理.通过使用dispatch_barrrier和dispatch_sync,你做到了让PhotoMana ...
- listview、gradview滚动到最后时,滑动至顶部
listview.gradview滑动顶端.底部的判断及底部滑动至顶端 mPhotoWall.setOnScrollListener(new AbsListView.OnScrollListener( ...
- 老板怎么办,我们网站遭到DDoS攻击又挂了?
相信现在正在阅读此文的你,一定听说过发生在上个月的史上最大的DDoS攻击. 美国东部时间2月28日,GitHub在一瞬间遭到高达1.35Tbps的带宽攻击.这次DDoS攻击几乎可以堪称是互联网有史以来 ...
- 教你在不使用框架的情况下也能写出现代化 PHP 代码
我为你们准备了一个富有挑战性的事情.接下来你们将以 无 框架的方式开启一个项目之旅. 首先声明, 这篇并非又臭又长的反框架裹脚布文章.也不是推销 非原创 思想 .毕竟, 我们还将在接下来的开发之旅中使 ...
- JAVA类的方法调用和变量(全套)
一.类的分类: 1.普通类 2.抽象类(含有抽象方法的类) 3.静态类(不需要实例化,就可以使用的类) 二.方法的分类: 1.私有方法(只有类的内部才可以访问的方法) 2.保护方法(只有类的内部和该该 ...
- python安装及写一个简单的验证码组件(配合node)
1.安装Python 到官网下载响应系统的版本(这里以windows为例):https://www.python.org/downloads/windows/ 然后就是不断地"下一步&quo ...
- 服务器Windows Server 2008 远程控制安全设置技巧
为了保障服务器远程控制操作的安全性,Windows Server 2008系统特意在这方面进行了强化,新推出了许多安全防范功能,不过有的功能在默认状态下并没有启用,这需要我们自行动手,对该系统进行合适 ...
- C语言学习之弹跳小球
重新回过头来看了一遍C语言,才发现我自己的无知,C语言其实好强大,我之前学的不过是一点C语法和做几个数学题.正好3月份的考试要考C语言,重新学一遍,先是在中国大学mooc上把翁恺老师的C语言刷了一遍, ...
- tensorflow安装篇
安装虚拟机redhat7u4-64 镜像文件在http://www.linuxfly.org/post/659 更换yum 参考https://blog.csdn.net/xiaoyiaoyou/ar ...
- Error loading MySQLdb module: No module named 'MySQLdb'----------- django成功连接mysql数据库的方法
在进行django学习过程中,尝试使用框架连接mysql数据库,启动服务器的时候经常遇到Error loading MySQLdb module: No module named 'MySQLdb' ...