3684: 大朋友和多叉树

题意:

求有n个叶子结点,非叶节点的孩子数量\(\in S, a \notin S\)的有根树个数,无标号,孩子有序。


鏼鏼鏼!

树的OGF:\(T(x) = \sum_{i\ge 0} t_ix^i\)

\[T(x) = x + \sum_{k \in S}T(x)^k
\]

因为一个树是叶子结点或者其他树拼接成的“序列”

\[x = T(x) -\sum_{k \in S}T(x)^k = G(T(x))
\]

所以\(T(x)\)是\(G(x) = x - \sum_{k \in S}x^k\)的复合逆,直接上拉格朗日反演求第n项的值

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = (1<<18) + 5;
inline int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
} int P = 950009857;
inline int Pow(ll a, int b) {
ll ans = 1;
for(; b; b>>=1, a=a*a%P)
if(b&1) ans=ans*a%P;
return ans;
} ll inv[N];
namespace ntt {
int g = 7, rev[N];
void dft(int *a, int n, int flag) {
int k = 0; while((1<<k) < n) k++;
for(int i=0; i<n; i++) {
rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
if(i < rev[i]) swap(a[i], a[rev[i]]);
}
for(int l=2; l<=n; l<<=1) {
int m = l>>1, wn = Pow(g, flag == 1 ? (P-1)/l : P-1-(P-1)/l);
for(int *p = a; p != a+n; p += l)
for(int k=0, w=1; k<m; k++, w = (ll)w*wn %P) {
int t = (ll) w * p[k+m] %P, r = p[k];
p[k+m] = (r - t + P) %P;
p[k] = (r + t) %P;
}
}
if(flag == -1) {
ll inv = Pow(n, P-2);
for(int i=0; i<n; i++) a[i] = a[i] * inv %P;
}
} void inverse(int *a, int *b, int l) {
static int t[N];
if(l == 1) {b[0] = Pow(a[0], P-2); return;}
inverse(a, b, l>>1);
int n = l<<1;
for(int i=0; i<l; i++) t[i] = a[i], t[i+l] = 0;
dft(t, n, 1); dft(b, n, 1);
for(int i=0; i<n; i++) b[i] = (ll) b[i] * (2 - (ll) t[i] * b[i] %P + P) %P;
dft(b, n, -1); for(int i=l; i<n; i++) b[i] = 0;
} void ln(int *a, int *b, int l) {
static int da[N], ia[N];
int n = l<<1;
for(int i=0; i<n; i++) da[i] = ia[i] = 0;
for(int i=0; i<l-1; i++) da[i] = (ll) (i+1) * a[i+1] %P;
inverse(a, ia, l);
dft(da, n, 1); dft(ia, n, 1);
for(int i=0; i<n; i++) b[i] = (ll) da[i] * ia[i] %P;
dft(b, n, -1);
for(int i=l-1; i>0; i--) b[i] = (ll) inv[i] * b[i-1] %P; b[0] = 0;
for(int i=l; i<n; i++) b[i] = 0;
} void exp(int *a, int *b, int l) {
static int t[N];
if(l == 1) {b[0] = 1; return;}
exp(a, b, l>>1);
int n = l<<1;
for(int i=0; i<n; i++) t[i] = 0;
ln(b, t, l);
for(int i=0; i<l; i++) t[i] = (a[i] - t[i] + P) %P; t[0] = (t[0] + 1) %P;
dft(b, n, 1); dft(t, n, 1);
for(int i=0; i<n; i++) b[i] = (ll) b[i] * t[i] %P;
dft(b, n, -1); for(int i=l; i<n; i++) b[i] = 0;
} void power(int *a, int k, int l) {
static int t[N];
int n = l<<1;
for(int i=0; i<n; i++) t[i] = 0;
ln(a, t, l);
for(int i=0; i<l; i++) t[i] = (ll) k * t[i] %P;
for(int i=0; i<n; i++) a[i] = 0;
exp(t, a, l);
}
} int n, m, g[N], a[N];
int main() {
//freopen("in", "r", stdin);
n=read(); m=read();
g[0] = 1;
for(int i=1; i<=m; i++) g[read()-1] = P-1;
int len = 1; while(len <= n) len <<= 1;
inv[1] = 1;
for(int i=2; i < len<<1; i++) inv[i] = (P - P/i) * inv[P%i] %P;
ntt::inverse(g, a, len); ntt::power(a, n, len);
int ans = (ll) a[n-1] * inv[n] %P;
printf("%d", ans);
}

BZOJ 3684: 大朋友和多叉树 [拉格朗日反演 多项式k次幂 生成函数]的更多相关文章

  1. BZOJ 3684 大朋友和多叉树

    BZOJ 3684 大朋友和多叉树 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的: ...

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

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

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

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

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

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

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

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

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

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

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

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

  8. loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)

    题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...

  9. [BZOJ 3652]大新闻

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

随机推荐

  1. 自定义省市选择器 微信小程序多列选择器

    由于微信小程序的选择器为省市区选择器共3列 如我仅需要省市2列的选择器 就需要我们另寻他法找来找去没有合适的 只能自己写了 1. 首先我们把所需要的省数据 市县数据放在一个 p_c.js 文件里面,使 ...

  2. 久未更 ~ 三之 —— CardView简单记录

    > > > > > 久未更 系列一:CardView 点击涟漪效果实现 //在 cardview 中 实现点击涟漪效果 android:clickable="t ...

  3. 从零开始学习前端JAVASCRIPT — 1、JavaScript基础

    1:定义:javascript是一种弱类型.动态类型.解释型的脚本语言. 弱类型:类型检查不严格,偏向于容忍隐式类型转换. 强类型:类型检查严格,偏向于不容忍隐式类型转换. 动态类型:运行的时候执行类 ...

  4. JAVA:成员变量和局部变量的区别

    1.作用于不同: 局部变量的作用域仅限于定义它的方法 成员变量的作用域在整个类的内部都是可见的 2.初始值不同 JAVA会给成员变量一个初始值 JAVA不会给局部变量赋予初始值 3.在同一个方法中,不 ...

  5. github 中删除仓库

    删除时,填充的名字是库的名字

  6. asp.net -mvc框架复习(4)-ASP.NET MVC中的约定规则

    1.路由规则 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System ...

  7. 转-CSS padding margin border属性详解

    原文链接:http://www.cnblogs.com/linjiqin/p/3556497.html 图解CSS padding.margin.border属性W3C组织建议把所有网页上的对像都放在 ...

  8. Maven 常用配置

    pom.xml基础配置: <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEn ...

  9. Jmeter_接口自动化基础流程概述

    这里补一篇基础的操作吧,不然总觉得没底! 1:创建一个线程组   2:添加一个cookie管理器   33333 3:设置你的信息头管理器:application/json;text/plain;ch ...

  10. Mac 管理员变为了普通用户怎么办?

    开机的时候一直按住 command+s 出现命令行终端的时候按照以下顺序输入命令: /sbin/mount -uw    回车rm var/db/.AppleSetupDone   回车 reboot ...