description

我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树。
考虑一个含有n个互异正整数的序列c[1],c[2],…,c[n]。如果一棵带点权的有根二叉树满足其所有顶点的权值都在集合{c[1],c[2],…,c[n]}中,我们的小朋友就会将其称作神犇的。并且他认为,一棵带点权的树的权值,是其所有顶点权值的总和。
给出一个整数m,你能对于任意的s(1<=s<=m)计算出权值为s的神犇二叉树的个数吗?请参照样例以更好的理解什么样的两棵二叉树会被视为不同的。
我们只需要知道答案关于998244353(7172^23+1,一个质数)取模后的值。
Input

第一行有2个整数 n,m(1<=n<=10^5; 1<=m<=10^5)。
第二行有n个用空格隔开的互异的整数 c[1],c[2],…,c[n](1<=c[i]<=10^5)。
Output

输出m行,每行有一个整数。第i行应当含有权值恰为i的神犇二叉树的总数。请输出答案关于998244353(=7172^23+1,一个质数)取模后的结果。
Sample Input
样例一:
2 3
1 2
样例二:
3 10
9 4 3
样例三:
5 10
13 10 6 4 15
Sample Output
样例一:
1
3
9
样例二:
0
0
1
1
0
2
4
2
6
15
样例三:
0
0
0
1
0
1
0
2
0
5
Hint

对于第一个样例,有9个权值恰好为3的神犇二叉树:

Source
VFleaKing & pyx1997 感谢wyl8899提供中文翻译

solution

取模俺就省略不写了
设f[i]f[i]f[i]:表示权值和为iii的本质不同的子树个数
g[i]g[i]g[i]:表示子树根节点是否属于∣C∣|C|∣C∣
则可以通过枚举左右儿子及自己本身的权值,列出最暴力简单的状态转移方程
fi=∑j=0ig[j]∑k=0i−jfkfi−j−kf_i=\sum_{j=0}^ig[j]\sum_{k=0}^{i-j}f_kf_{i-j-k}fi​=j=0∑i​g[j]k=0∑i−j​fk​fi−j−k​
这无非是一个卷积再卷积的形式,于是就跟生成函数沾边了
令fff序列的生成函数为F(x)F(x)F(x),ggg序列的生成函数为G(x)G(x)G(x),则有
F=G×F2+1F=G\times F^2+1F=G×F2+1
加1是因为这个子树可能是只有根节点的
F=G×F2+1⇔GF2−F+1=0⇒F=1±1−4G2G⇒F=1−1−4G2GF=G\times F^2+1\Leftrightarrow GF^2-F+1=0\Rightarrow F=\frac{1±\sqrt{1-4G}}{2G}\Rightarrow F=\frac{1-\sqrt{1-4G}}{2G}F=G×F2+1⇔GF2−F+1=0⇒F=2G1±1−4G​​⇒F=2G1−1−4G​​
套上多项式开根与多项式求逆即可
是一道码农题

code

#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
#define mod 998244353
#define maxn 300005
int inv2;
int r[maxn], c[maxn], v[maxn], ni[maxn];
int A[maxn], B[maxn], F[maxn], G[maxn];int qkpow( int x, int y ) {int ans = 1;while( y ) {if( y & 1 ) ans = ans * x % mod;x = x * x % mod;y >>= 1;}return ans;
}void NTT( int *h, int opt, int n ) {int len = 1, l = 0;while( len < n ) len <<= 1, l ++;for( int i = 0;i < len;i ++ )r[i] = ( r[i >> 1] >> 1 ) | ( ( i & 1 ) << ( l - 1 ) );for( int i = 0;i < len;i ++ ) if( i < r[i] ) swap( h[i], h[r[i]] );for( int i = 1;i < len;i <<= 1 ) {int omega = qkpow( opt == 1 ? 3 : mod / 3 + 1, ( mod - 1 ) / ( i << 1 ) );for( int j = 0;j < len;j += ( i << 1 ) )for( int k = 0, w = 1;k < i;k ++, w = w * omega % mod ) {int x = h[j + k], y = h[j + k + i] * w % mod;h[j + k] = ( x + y ) % mod;h[j + k + i] = ( x - y + mod ) % mod;}}if( opt == -1 ) {int inv = qkpow( len, mod - 2 );for( int i = 0;i < len;i ++ )h[i] = h[i] * inv % mod;}
}void polyinv( int n, int *f, int *g ) {if( n == 1 ) { g[0] = qkpow( f[0], mod - 2 ); return; }polyinv( ( n + 1 ) >> 1, f, g );for( int i = 0;i < n;i ++ ) A[i] = f[i], B[i] = g[i];NTT( A, 1, n << 1 );NTT( B, 1, n << 1 );for( int i = 0;i < ( n << 1 );i ++ ) A[i] = A[i] * B[i] % mod * B[i] % mod;NTT( A, -1, n << 1 );for( int i = 0;i < n;i ++ )g[i] = ( g[i] + g[i] - A[i] + mod ) % mod;for( int i = 0;i < ( n << 1 );i ++ ) A[i] = B[i] = 0;
}void polysqrt( int n, int *f, int *g ) {if( n == 1 ) { g[0] = 1; return; }polysqrt( ( n + 1 ) >> 1, f, g );for( int i = 0;i < n;i ++ ) F[i] = f[i];polyinv( n, g, G );NTT( F, 1, n << 1 );NTT( G, 1, n << 1 );for( int i = 0;i < ( n << 1 );i ++ ) G[i] = G[i] * F[i] % mod;NTT( G, -1, n << 1 );for( int i = 0;i < n;i ++ )g[i] = ( G[i] + g[i] ) % mod * inv2 % mod;for( int i = 0;i < ( n << 1 );i ++ ) F[i] = G[i] = 0;
}signed main() {inv2 = qkpow( 2, mod - 2 );int n, m;scanf( "%lld %lld", &n, &m );for( int i = 1, x;i <= n;i ++ ) {scanf( "%lld", &x );c[x] ++;}int len = 1;while( len <= m ) len <<= 1;for( int i = 0;i < len;i ++ )c[i] = mod - ( c[i] << 2 );c[0] ++;polysqrt( len, c, v );v[0] = ( v[0] + 1 ) % mod;polyinv( len, v, ni );for( int i = 1;i <= m;i ++ )printf( "%lld\n", ( ni[i] << 1 ) % mod );return 0;
}

[bzoj3625][Codeforces Round #250]小朋友和二叉树 (生成函数)相关推荐

  1. Codeforces Round #250 (Div. 2) A - The Child and Homework

    传送门Codeforces Round #250 (Div. 2) A - The Child and Homework 第一次做完之后交上去,过了例子.顺手就锁定了...然后一个小时之后就被HACK ...

  2. Codeforces Round 250(Div. 2)

    layout: post title: Codeforces Round 250 (Div. 2) author: "luowentaoaa" catalog: true tags ...

  3. Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸

    D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...

  4. [Codeforces Round #250 (Div. 1) -D] The Child and Sequence

    Codeforces传送门 洛谷传送门 题意翻译 给定数列,区间查询和,区间取模,单点修改. n,m≤105n,m≤105n,m\le 10^5 题目描述 At the children's day, ...

  5. Codeforces Round #250 (Div. 2) (ABCD题解)

    比赛链接:http://codeforces.com/contest/437 A. The Child and Homework time limit per test:1 second memory ...

  6. Codeforces Round #250 (Div. 2)—A. The Child and Homework

         好题啊,被HACK了.曾经做题都是人数越来越多.这次比赛 PASS人数 从2000直掉 1000人  被HACK  1000多人! ! ! ! 没见过的科技啊 1 2 4 8 这组数 被黑的 ...

  7. Lust(Codeforces Round #446 Div.1-891E)(母函数\生成函数)

    文章目录 题目 思路 代码 题目 你有n个数 a1,a2,...,ana_1,a_2,...,a_na1​,a2​,...,an​ ,要进行 kkk 次操作,每次在 111 ~ nnn 中随机选择一个 ...

  8. [bzoj3625][Codeforces 250 E]The Child and Binary Tree(生成函数+多项式运算+FFT)

    3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 650  Solved: 2 ...

  9. Educational Codeforces Round 114 (Rated for Div. 2) (A ~ F)全题解

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Educational Codeforces Round 114 (Rated for Div. 2) ...

最新文章

  1. AI传教士和野人渡河问题-实验报告
  2. c语言课程设计坦克大战,funcodec++课程设计_坦克大战
  3. OpenCv实现两幅图像的拼接
  4. python 日志打印
  5. xy坐标正负方向_道路施工图纸上x坐标和y坐标分别代表什么方向,哪个代表南北方向,哪个代表东西方向?...
  6. [转]easyui 全部图标
  7. 物流系统车辆仓库定位的实现——基于RFID定位的实现方法
  8. Vue常用特性~非常详细哦,带源码资料
  9. envi栅格TIF数据进行分割_常用水文气象数据读取及其可视化(二进制、HDF5、NetCDF)以GLDAS、MODIS、GSMaP为例...
  10. 用了这么久的 Chrome,你不会还没掌握这个功能吧?
  11. SSH config 文件的作用
  12. 更改不了html的默认程序,解决烦人的Windows10系统无法更改默认应用程序的怪问题...
  13. c语言printf分析,C语言 printf详解
  14. 锁定计算机和睡眠有什么区别,电脑休眠和睡眠哪个好?电脑计算机睡眠和休眠有什么区别...
  15. 新加坡10月新人扎堆结婚,只要生娃政府就发3000新币
  16. golang对比python
  17. 四川企立方电商:拼多多降价导致降权怎么
  18. 2023最近很火的抖音解封技术教程分析+价值1000+
  19. 性能架构师看IT之家的性能问题及解法
  20. 基于元路径的利用多级社会背景信息的虚假新闻检测

热门文章

  1. 如何用TensorFlow实现人工智能?
  2. 语言怎么得到直流电压并采样_交流电AC如何转换成直流电DC?
  3. 独占设备的分配与回收_灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?...
  4. liunx+java+jar+运行_Linux后台运行java的jar包
  5. springmvc如何使用视图解析器_SpringMVC工作原理
  6. ubuntu mysql集群搭建_ubuntu server部署mysql集群
  7. maya的颤动怎么做_必看!新手学习MAYA的几个建议
  8. 软件构造学习笔记-实验2
  9. leetcode377. 组合总和 Ⅳ
  10. JAVA开发需求分析套路_毕设做什么好?感觉都是套路了