整理的算法模板合集: ACM模板


点我看多项式全家桶(●^◡_◡◡​^●)

CF438E The Child and Binary Tree

简单的黑题

首先我们发现模数为998244353998244353998244353,很自然的想到NTT!!!想到用多项式来求解本题。

具有同样效果的数字还有:1004535809、469762049…1004535809、469762049 \dots1004535809、469762049…

显然: 998244353→NTT998244353\to NTT998244353→NTT(bushi)题目中要求的是权值和为 sss 方案数,即点集中选取若干个点组成一颗权值和为 sss 的树的方案数,经典生成函数。我们设序列 fif_ifi​ 表示权值和为 iii 的符合条件的二叉树的个数,gig_igi​​ 表示权值 iii 是否包含在 ccc 中,显然有 f0=1f_0=1f0​=1,根据题意可得:
fn=∑i=1ngi∑j=1n−ifjfn−i−j[n>0]f_n=\sum_{i=1}^ng_i\sum_{j=1}^{n-i}f_jf_{n-i-j}[n>0]fn​=i=1∑n​gi​j=1∑n−i​fj​fn−i−j​[n>0]

经典操作,输入的时候处理一下 gig_igi​ ,经典动规及乘法原理:权值和为 nnn 的方案数 === 权值和为 jjj 的方案数 ×\times× 权值和为 n−i−jn-i-jn−i−j 的方案数 ×gi(i是否存在)\times\ g_i\ (\text{i是否存在})× gi​ (i是否存在) 我们只需要令 FFF 表示序列 fff 的生成函数,GGG 表示序列 ggg 的生成函数。 则:F=G×F2+1F=G\times F^2+1F=G×F2+1。生成函数 GGG 已经预处理了,求出 FFF 即可。问题变成了一个一元二次方程,显然可以直接使用求根公式:F=1±1−4G2GF=\cfrac{1± \sqrt{1-4G}}{2G}F=2G1±1−4G​​。 因为 2G2G2G 可能为 000 不可求逆,所以需要化简移项: F=21±1−4GF=\cfrac{2}{1±\sqrt{1-4G}}F=1±1−4G​2​。因为 F0=1,G0=0F_0=1,G_0=0F0​=1,G0​=0,代入发现当且仅当符号取 +++ 时初始值成立, 故取 +++ ,即:F=21+1−4GF=\cfrac{2}{1+\sqrt{1-4G}}F=1+1−4G​2​

我们直接多项式开根 + 多项式求逆即可。

//#pragma GCC optimize(2)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;const int N = 1000007;
const int p = 998244353, gg = 3, ig = 332738118, img = 86583718;
const int mod = 998244353;template <typename T>void read(T &x)
{x = 0;register int f = 1;register char ch = getchar();while(ch < '0' || ch > '9') {if(ch == '-')f = -1;ch = getchar();}while(ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}x *= f;
}int qpow(int a, int b)
{int res = 1;while(b) {if(b & 1) res = 1ll * res * a % mod;a = 1ll * a * a % mod;b >>= 1;}return res;
}namespace Poly
{#define mul(x, y) (1ll * x * y >= mod ? 1ll * x * y % mod : 1ll * x * y)#define minus(x, y) (1ll * x - y < 0 ? 1ll * x - y + mod : 1ll * x - y)#define plus(x, y) (1ll * x + y >= mod ? 1ll * x + y - mod : 1ll * x + y)#define ck(x) (x >= mod ? x - mod : x)//取模运算太慢了typedef vector<int> poly;const int G = 5;const int inv_G = qpow(G, mod - 2);int RR[N], deer[2][19][N], inv[N];void init(const int t) {//预处理出来NTT里需要的w和wn,砍掉了一个log的时间for(int p = 1; p <= t; ++ p) {int buf1 = qpow(G, (mod - 1) / (1 << p));int buf0 = qpow(inv_G, (mod - 1) / (1 << p));deer[0][p][0] = deer[1][p][0] = 1;for(int i = 1; i < (1 << p); ++ i) {deer[0][p][i] = 1ll * deer[0][p][i - 1] * buf0 % mod;//逆deer[1][p][i] = 1ll * deer[1][p][i - 1] * buf1 % mod;}}inv[1] = 1;for(int i = 2; i <= (1 << t); ++ i)inv[i] = 1ll * inv[mod % i] * (mod - mod / i) % mod;}int NTT_init(int n) {//快速数论变换预处理int limit = 1, L = 0;while(limit < n) limit <<= 1, L ++ ;for(int i = 0; i < limit; ++ i)RR[i] = (RR[i >> 1] >> 1) | ((i & 1) << (L - 1));return limit;}void NTT(poly &A, int type, int limit) {//快速数论变换A.resize(limit);for(int i = 0; i < limit; ++ i)if(i < RR[i])swap(A[i], A[RR[i]]);for(int mid = 2, j = 1; mid <= limit; mid <<= 1, ++ j) {int len = mid >> 1;for(int pos = 0; pos < limit; pos += mid) {int *wn = deer[type][j];for(int i = pos; i < pos + len; ++ i, ++ wn) {int tmp = 1ll * (*wn) * A[i + len] % mod;A[i + len] = ck(A[i] - tmp + mod);A[i] = ck(A[i] + tmp);}}}if(type == 0) {for(int i = 0; i < limit; ++ i)A[i] = 1ll * A[i] * inv[limit] % mod;}}poly poly_mul(poly A, poly B) {//多项式乘法int deg = A.size() + B.size() - 1;int limit = NTT_init(deg);poly C(limit);NTT(A, 1, limit);NTT(B, 1, limit);for(int i = 0; i < limit; ++ i)C[i] = 1ll * A[i] * B[i] % mod;NTT(C, 0, limit);C.resize(deg);return C;}poly poly_inv(poly &f, int deg) {//多项式求逆if(deg == 1)return poly(1, qpow(f[0], mod - 2));poly A(f.begin(), f.begin() + deg);poly B = poly_inv(f, (deg + 1) >> 1);int limit = NTT_init(deg << 1);NTT(A, 1, limit), NTT(B, 1, limit);for(int i = 0; i < limit; ++ i)A[i] = B[i] * (2 - 1ll * A[i] * B[i] % mod + mod) % mod;NTT(A, 0, limit);A.resize(deg);return A;}poly poly_sqrt(poly &f, int deg) {//多项式开方if(deg == 1) return poly(1, 1);poly A(f.begin(), f.begin() + deg);poly B = poly_sqrt(f, (deg + 1) >> 1);poly IB = poly_inv(B, deg);int limit = NTT_init(deg << 1);NTT(A, 1, limit), NTT(IB, 1, limit);for(int i = 0; i < limit; ++ i)A[i] = 1ll * A[i] * IB[i] % mod;NTT(A, 0, limit);for(int i =0; i < deg; ++ i)A[i] = 1ll * (A[i] + B[i]) * inv[2] % mod;A.resize(deg);return A;}
}using Poly::poly;
using Poly::poly_sqrt;
using Poly::poly_inv;int n, m, x, k, type;char s[N];
int cnt;int main()
{Poly::init(18);//2^21 = 2,097,152,根据题目数据多项式项数的大小自由调整,注意大小需要跟deer数组同步(21+1=22)read(n), read(m);poly f(N), g(N), tmp(N);for(int i = 0; i < n; ++ i)read(x), g[x] = 1;tmp[0] = 1;for(int i = 1; i <= m; ++ i) tmp[i] = mod - 4 * g[i] % mod;g = poly_sqrt(tmp, m + 1);++ g[0];f = poly_inv(g, m + 1);for(int i = 1; i <= m; ++ i) f[i] = f[i] * 2 % mod;for(int i = 1; i <= m; ++ i) printf("%d\n", f[i]);return 0;
}

CF438E The Child and Binary Tree(有意思的生成函数 + 多项式求逆 + 多项式开方)相关推荐

  1. CF438E The Child and Binary Tree 生成函数、多项式开根

    传送门 设生成函数\(C(x) = \sum\limits_{i=0}^\infty [\exists c_j = i]x^i\),答案数组为\(f_1 , f_2 , ..., f_m\),\(F( ...

  2. E. The Child and Binary Tree(生成函数 + 多项式)

    E. The Child and Binary Tree 不难写出一个递推式fn=∑i=1ngi∑j=0n−ifjfn−i−jf_n = \sum\limits_{i = 1} ^{n}g_i \su ...

  3. CF438E-The Child and Binary Tree【生成函数】

    正题 题目链接:https://www.luogu.com.cn/problem/CF438E 题目大意 每个节点有nnn个权值可以选择,对于1∼m1\sim m1∼m中的每个数字kkk,求权值和为k ...

  4. CF438E:The Child and Binary Tree(生成函数)

    解析: 设计 fif_ifi​ 表示权值为 iii 的方案数,f0=1f_0=1f0​=1. 枚举根节点权值,可以写出转移: fn=∑gk∑ififn−k−i=∑i+j+k=nfifjgkf_n=\s ...

  5. [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 ...

  6. bzoj 3625(CF 438E)The Child and Binary Tree——多项式开方

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3625 http://codeforces.com/contest/438/problem/E ...

  7. PAT(甲级)2019年春季考试 7-4 Structure of a Binary Tree

    目录 整体思路 犯的错误 代码 整体思路 1.先根据后序和中序序列建树,老生常谈,记得返回root 2.对树进行BFS,在这个过程中用hash的方式记录下每个值对应的父节点.左孩子.右孩子的值,记录下 ...

  8. LeetCode 102. Binary Tree Level Order Traversal--递归,迭代-Python,Java解法

    题目地址: Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to ...

  9. PAT甲级——1102 Invert a Binary Tree (层序遍历+中序遍历)

    本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90577042 1102 Invert a Binary Tree ...

最新文章

  1. 土壤生物和生化专业委员会暨土壤生物与土壤健康研讨会(杭州5月8-11)
  2. Android --- SharedPreferences的详细介绍
  3. 数字电路是如何搭建的
  4. Python实现ORM
  5. 属于程序员的黄金五年,把握这 5 年,或将迎来美好的职场生活!
  6. 添加 code snippets (转)
  7. excel vsto 功能菜单定义
  8. MIT Place Pulse数据集及google街景图片爬取
  9. EasyUI整站示例系统-SyPro
  10. Vue安装教程(保姆级详细教程)
  11. android 标签云圆形,JavaScript实现的圆形浮动标签云效果实例
  12. android支付宝转跳转,APP跳转支付宝指定界面
  13. centos6和centos7的主要区别和版本选择
  14. 【U3D实战笔记】2DProject:RushMan
  15. 再见了,华为!活命要紧 ~
  16. 计算机网络胡工程施工税率,弱电项目增值税6%、9%、13%税率怎样区分?项目经理必知...
  17. 微信公众开发URL和token填写详解
  18. CMake中find_package的学习
  19. 【Rust日报】2022-12-11 EDMA:用 Rust 编写的嵌入式数据库管理终端应用程序
  20. 简单工厂创建不同几何图形(Java代码实例)

热门文章

  1. 栈与队列2——两个栈组成队列
  2. 网络安全与机器学习(二):网络安全任务如何结合机器学习?
  3. Electron的代码调试
  4. windows server 2016 安装指南
  5. vue vue-router vuex element-ui axios 的学习笔记(七)完善登录注册
  6. 怎样在nexus 中 搜索到远程maven仓库中的jar 文件
  7. day02 cssjs 基础
  8. 知名财经大V称:京东金融遇到了点“问题”!
  9. 【微信公众号开发】获取并保存access_token、jsapi_ticket票据(可用于微信分享、语音识别等等)...
  10. 网络故障排除连载之一:常用排除方法综述