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);
}

最新文章

  1. ActiveMQ笔记(2):基于ZooKeeper的HA方案
  2. 我的ORM之二--添加
  3. VS经常报错的link error 2019
  4. 自定义input[type=&quot;file&quot;]的样式
  5. c# equals和==的区别
  6. 502 Bad Gateway nginx 解决
  7. WPF样式——多条件触发器
  8. URAL 1012 K-based Numbers. Version 2(DP+高精度)
  9. 7款纯CSS3实现的炫酷动画应用|慕课网只学有用的!
  10. Team Foundation Server 2013 Update 3 下载激活
  11. [转]编写高性能的Lua代码
  12. COGS 1299. bplusa【听说比a+b还要水的大水题???】
  13. Java 获取年月日方法
  14. java基础复习1
  15. ionic3创建选项卡
  16. SpringBoot相关错误
  17. String 相关
  18. golang使用 gzip压缩
  19. Tomcat类加载架构
  20. javascript如何处理很多数据,类似分页切换

热门文章

  1. BZOJ1294: [SCOI2009]围豆豆Bean
  2. js根据出生年月日换算年龄
  3. jquery1.8 在IE8 下面报错:对象不支持此属性或方法 return b.getAttribute(&quot;id&quot;)===a
  4. javascript之fill()方法
  5. DEDECMS系统安全篇之移data目录到Web根目录以外听语音
  6. angular 4 http 之web api 服务
  7. input===》name属性异常错误
  8. 序列化和Json
  9. 剑指offfer:二维数组中的查找
  10. Linxu指令--crond