BZOJ 3684: 大朋友和多叉树 [拉格朗日反演 多项式k次幂 生成函数]
3684: 大朋友和多叉树
题意:
求有n个叶子结点,非叶节点的孩子数量\(\in S, a \notin S\)的有根树个数,无标号,孩子有序。
鏼鏼鏼!
树的OGF:\(T(x) = \sum_{i\ge 0} t_ix^i\)
\]
因为一个树是叶子结点或者其他树拼接成的“序列”
\]
所以\(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次幂 生成函数]的更多相关文章
- BZOJ 3684 大朋友和多叉树
BZOJ 3684 大朋友和多叉树 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的: ...
- 【BZOJ3684】大朋友和多叉树(拉格朗日反演)
题目链接 题意 求满足如下条件的多叉树个数: 1.每一个点的儿子个数在给定的集合 \(S\) 内 2.总的叶子节点树为 \(s\) 儿子之间有顺序关系,但节点是没有标号的. Sol 拉格朗日反演板子题 ...
- [BZOJ3684][拉格朗日反演+多项式求幂]大朋友和多叉树
题面 Description 我们的大朋友很喜欢计算机科学,而且尤其喜欢多叉树.对于一棵带有正整数点权的有根多叉树,如果它满足这样的性质,我们的大朋友就会将其称作神犇的:点权为\(1\)的结点是叶子结 ...
- 【bzoj3684】 大朋友和多叉树 生成函数+多项式快速幂+拉格朗日反演
这题一看就觉得是生成函数的题... 我们不妨去推下此题的生成函数,设生成函数为$F(x)$,则$[x^s]F(x)$即为答案. 根据题意,我们得到 $F(x)=x+\sum_{i∈D} F^i(x)$ ...
- 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* ...
- BZOJ3684 大朋友和多叉树(多项式相关计算)
设$f(x)$为树的生成函数,即$x^i$的系数为根节点权值为$i$的树的个数.不难得出$f(x)=\sum_{k\in D}f(x)^k+x$我们要求这个多项式的第$n$项,由拉格朗日反演可得$[x ...
- loj#6363. 「地底蔷薇」(拉格朗日反演+多项式全家桶)
题面 传送门 题解 肝了一个下午--我老是忘了拉格朗日反演计算的时候多项式要除以一个\(x\)--结果看它推倒简直一脸懵逼-- 做这题首先你得知道拉格朗日反演是个什么东西->这里 请坐稳,接下来 ...
- [BZOJ 3652]大新闻
[BZOJ 3652] 大新闻 题意 随机从 \([0,n)\) 中选取一个整数 \(x\), 并从 \([0,n)\) 中再选取一个整数 \(y\). 有 \(p\) 的概率选取一个能令 \(x\o ...
随机推荐
- 去除FineReport报表点击单元格时出现的黑框
选择模版->模版web属性 添加加载结束事件,具体代码如下 $("td").bind("click",function(){return false;}) ...
- 【分享】一个集成tracert和ping的网络监测工具
最近接到一个需求,需求背景是这样的:目前Windows平台下本身都有tracert和ping的实现,而且可以直接在cmd下使用. 需求中有两个要求: 1. Windows平台中的tracert执行速度 ...
- JavaScript基础:DOM操作详解
本文最初发表于博客园,并在GitHub上持续更新前端的系列文章.欢迎在GitHub上关注我,一起入门和进阶前端. 以下是正文. 前言 JavaScript的组成 JavaScript基础分为三个部分: ...
- ProtoBuf 与 gRPC
用 Protobuf 很久了,但是一直觉得很简单,所以就没有做一个总结,今天想尝试一下 gRPC,顺带就一起总结一下.ProtoBuf 是个老同志了,应该是 2010 的时候发布的,然后被广泛使用,目 ...
- (Release Candidate)Candidate
RC:(Release Candidate)Candidate是候选人的意思,用在软件或者操作系统上就是候选版本
- 在MAC电脑上抓取iphone数据包的方法
一.说明: 1.整个抓包操作的过程中,手机必须一直通过USB链接MAC电脑 2.手机系统要求在IOS5以上,因为使用的RVI技术在IOS5以后的系统中才有 3.抓包过程中,手机可以使用任何网络2G.3 ...
- CPU频率
CPU频率 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的同步脉冲数)的简称. 概念 CPU频率,就是CPU的时钟频率,简单说是CPU运算时的工作的频率(1秒内发生的 ...
- CCF系列之有趣的数(201312-4)
题目链接: http://115.28.138.223:81/view.page?opid=4 试题名称: 有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 我们把一个 ...
- Number()和new Number()的区别以及一种简单实现
看MDN Beginners文档的时候注意到了这种用法 var n1 = Number(123); , 冒出的第一个疑问就是和 var n2 = new Number(123); 有什么区别呢? 首先 ...
- Mysql覆盖索引 covering index 或者 index coverage
组合索引 提到组合索引,大家都知道"最左前缀"原则.例如,创建索引 idx_name_age (name,age) ,通常情况下,where age=50 或者 where age ...