[luogu5162]WD与积木
设$g_{n}$表示$n$个积木放的方案数,枚举最后一层所放的积木,则有$g_{n}=\sum_{i=1}^{n}c(n,i)g_{n-i}$(因为积木有编号的所以要选出$i$个)
将组合数展开并化简,得到$\frac{g_{n}}{n!}=\sum_{i=1}^{n}\frac{g_{n-i}}{i!(n-i)!}$,明显是一个分治fft的形式,转换为多项式求逆:
令$g_{n}$的指数生成函数为$G(x)=\sum_{i=0}^{\infty}\frac{g_{i}}{i!}x^{i}$,再令$H(x)=\sum_{i=0}^{\infty}\frac{x^{i}}{i!}$,考虑$H(x)G(x)$,代入并将$i=0$和$j=0$提出可得$H(x)G(x)=\sum_{i=0}^{\infty}(\sum_{j=0}^{i}H(x)[j]\cdot G(x)[i-j])x^{i}=2G(x)-1$,即$G(x)=\frac{1}{2-H(x)}$
设$f_{n}$表示$n$个积木放的方案数的层数之和,那么根据期望的定义,答案$E=\frac{f_{n}}{g_{n}}$
类似的,可以写出$f_{n}$的递推式,即$f_{n}=g_{n}+\sum_{i=1}^{n}c(n,i)f_{n-i}$($g_{n}$是因为每一个方案都要+1),将$g_{n}$的表达式展开,有$\frac{f_{n}}{n!}=\sum_{i=1}^{n}\frac{f_{n-i}+g_{n-i}}{i!(n-i)!}$,同样去转换为多项式求逆:
令$f_{n}$的指数生成函数为$F(x)=\sum_{i=0}^{\infty}\frac{f_{i}}{i!}x^{i}$,$H(x)$和$G(x)$相同,考虑$H(x)(G(x)+F(x))$,类似上面可得$H(x)(G(x)+F(x))=G(x)+2F(x)$(注意$f_{0}=0$),即$F(x)=\frac{(H(x)-1)G(x)}{2-H(x)}=(H(x)-1)G(x)^{2}$
最终答案即$\frac{F(x)[n]}{G(x)[n]}$(都除以了$n!$),注意最后一步不能将$\frac{F(x)}{G(x)}$作为结果,因为这不等于答案

1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N (1<<18)
4 #define mod 998244353
5 int t,n,a[N],c[N],h[N],g[N],f[N];
6 int ksm(int n,int m){
7 if (!m)return 1;
8 int s=ksm(n,m>>1);
9 s=1LL*s*s%mod;
10 if (m&1)s=1LL*s*n%mod;
11 return s;
12 }
13 void ntt(int *a,int n,int p){
14 for(int i=0;i<(1<<n);i++){
15 int rev=0;
16 for(int j=0;j<n;j++)rev=rev*2+((i&(1<<j))>0);
17 if (i<rev)swap(a[i],a[rev]);
18 }
19 for(int i=2;i<=(1<<n);i*=2){
20 int s=ksm(3,(mod-1)/i);
21 if (p)s=ksm(s,mod-2);
22 for(int j=0;j<(1<<n);j+=i)
23 for(int k=0,ss=1;k<(i>>1);k++,ss=1LL*ss*s%mod){
24 int x=a[j+k],y=1LL*a[j+k+(i>>1)]*ss%mod;
25 a[j+k]=(x+y)%mod;
26 a[j+k+(i>>1)]=(x+mod-y)%mod;
27 }
28 }
29 if (p){
30 int s=ksm((1<<n),mod-2);
31 for(int i=0;i<(1<<n);i++)a[i]=1LL*a[i]*s%mod;
32 }
33 }
34 void Inv(int *a,int *b,int n){
35 if (!n){
36 b[0]=ksm(a[0],mod-2);
37 return;
38 }
39 Inv(a,b,n-1);
40 for(int i=0;i<(1<<n);i++)c[i]=a[i];
41 for(int i=(1<<n);i<(1<<n+1);i++)c[i]=0;
42 ntt(c,n+1,0);
43 ntt(b,n+1,0);
44 for(int i=0;i<(1<<n+1);i++)b[i]=1LL*b[i]*(mod+2-1LL*c[i]*b[i]%mod)%mod;
45 ntt(b,n+1,1);
46 for(int i=(1<<n);i<(1<<n+1);i++)b[i]=0;
47 }
48 int main(){
49 a[0]=1;
50 for(int i=1;i<N;i++)a[i]=1LL*a[i-1]*ksm(i,mod-2)%mod;
51 h[0]=(mod+2-a[0])%mod;
52 for(int i=1;i<N/2;i++)h[i]=(mod-a[i])%mod;
53 Inv(h,g,17);
54 memcpy(f,g,sizeof(g));
55 ntt(f,18,0);
56 for(int i=0;i<N;i++)f[i]=1LL*f[i]*f[i]%mod;
57 ntt(f,18,1);
58 for(int i=N/2;i<N;i++)f[i]=0;
59 ntt(f,18,0);
60 h[0]=0;
61 for(int i=1;i<N/2;i++)h[i]=a[i];
62 ntt(h,18,0);
63 for(int i=0;i<N;i++)f[i]=1LL*f[i]*h[i]%mod;
64 ntt(f,18,1);
65 scanf("%d",&t);
66 while (t--){
67 scanf("%d",&n);
68 printf("%lld\n",1LL*f[n]*ksm(g[n],mod-2)%mod);
69 }
70 }
[luogu5162]WD与积木的更多相关文章
- Luogu5162 WD与积木(生成函数+多项式求逆)
显然的做法是求出斯特林数,但没有什么优化空间. 考虑一种暴力dp,即设f[i]为i块积木的所有方案层数之和,g[i]为i块积木的方案数.转移时枚举第一层是哪些积木,于是有f[i]=g[i]+ΣC(i, ...
- [Luogu5162]WD与积木(多项式求逆)
不要以为用上Stirling数就一定离正解更近,FFT都是从DP式本身出发的. 设f[i]为i个积木的所有方案的层数总和,g[i]为i个积木的方案数,则答案为$\frac{f[i]}{g[i]}$ 转 ...
- 洛谷 P5162 WD与积木 解题报告
P5162 WD与积木 题目背景 WD整日沉浸在积木中,无法自拔-- 题目描述 WD想买\(n\)块积木,商场中每块积木的高度都是\(1\),俯视图为正方形(边长不一定相同).由于一些特殊原因,商家会 ...
- [P5162] WD与积木
每种堆法(理解成名次序列,举例3,3,8,2和7,7,100,2都对应2,2,1,3这个名次序列)等概率出现:题目中"两种堆法不同当且仅当某个积木在两种堆法中处于不同的层中"可见这 ...
- 洛谷P5162 WD与积木 [DP,NTT]
传送门 思路 真是非常套路的一道题-- 考虑\(DP\):设\(f_n\)为\(n\)个积木能搭出的方案数,\(g_n\)为所有方案的高度之和. 容易得到转移方程: \[ \begin{align*} ...
- 洛谷 P5162 WD与积木【多项式求逆】
设f[i]为i个积木能堆出来的种类,g[i]为i个积木能堆出来的种类和 \[ f[n]=\sum_{i=1}^{n}C_{n}^{i}g[n-i] \] \[ g[n]=\sum_{i=1}^{n}C ...
- P5162 WD与积木(多项式求逆+生成函数)
传送门 题解 比赛的时候光顾着算某一个\(n\)的答案是多少忘了考虑不同的\(n\)之间的联系了--而且我也很想知道为什么推着推着会变成一个二项式反演-- 设\(f_n\)为\(n\)块积木时的总的层 ...
- 【LUOGU???】WD与积木 NTT
题目大意 把 \(n\) 个有标号物品分到一些有标号的箱子中且不允许为空,问期望箱子的数量. 多组询问. \(n\leq 100000\) 题解 记 \(f_i\) 为 \(i\) 个有标号物品分到一 ...
- 【LGP5162】WD与积木
题目 场面过度玄学,容易引起不适 我们发现我们要求的这个期望由分母和分子两部分构成 易发现 \[Ans=\frac{\sum_{i=1}^nS_2(n,i)\times i\times i!}{\su ...
随机推荐
- SQL实例_11Oracle基本操作
前言导读 本章介绍了在正常使用Oracle数据库之前进行的常规操作 本章语句的运行需要子啊PLSQL软件中运行 本章导入导出语句需要在虚拟环境中直接运行 1 Oracle创建表空间和用户 --1 创建 ...
- 初识Linux shell
目录 初识Linux shell Linux 深入探究Linux内核 系统内存管理 交换空间 页面 换出 软件程序管理 Linux中的进程 Linux系统的运行级 硬件设备管理 插入设备驱动代码的方法 ...
- python的参数传递是值传递还是引用传递??
函数参数传递机制,传值和引用的是什么意思? 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题.基本的参数传递机制有两种:值传递和引用传递. 值传递(pa ...
- BUAA 2020 软件工程 个人项目作业
BUAA 2020 软件工程 个人项目作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 个人项目作业 ...
- Spring动态添加定时任务
Spring动态添加定时任务 一.背景 二.需求和实现思路 1.能够动态的添加一个定时任务. 2.能够取消定时任务的执行. 3.动态的修改任务执行的时间. 4.获取定时任务执行的异常 三.代码实现 四 ...
- 简明教程 | Docker篇 · 其二:Dockerfile的编写
Dockerfile是什么 一个包含用于组合 image 的命令的文本文件,docker 通过 dockerfile 和构建环境的上下文来构建 image . 编写Dockerfile FROM 首先 ...
- 为什么用于开关电源的开关管一般用MOS管而不是三极管
区别: 1.MOS管损耗比三极管小,导通后压降理论上为0. 2.MOS管为电压驱动型,只需要给电压即可,意思是即便串入一个100K的电阻,只要电压够,MOS管还是能够导通. 3.MOS管的温度特性要比 ...
- 21.10.9 test
T1 购票方案 \(\color{green}{100}\) 对于每个时间节点维护它作为每种票所能包含的最后一个点时,这种票的起始点位置,由于这个位置是单调的,所以类似双指针维护,\(O(KN)\) ...
- MySQL 的架构与组件
MySQL 的逻辑架构图设计图 连接/线程处理:管理客户端连接/会话[mysql threads] 解析器:通过检查SQL查询中的每个字符来检查SQL语法,并为每个SQL查询生成 SQL_ID. 此 ...
- 决策树 机器学习,西瓜书p80 表4.2 使用信息增益生成决策树及后剪枝
使用信息增益构造决策树,完成后剪枝 目录 使用信息增益构造决策树,完成后剪枝 1 构造决策树 1 根结点的选择 色泽 信息增益 根蒂 信息增益 敲声 信息增益 纹理 信息增益 脐部 信息增益 触感 信 ...