BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]
4555: [Tjoi2016&Heoi2016]求和
题意:求$$
\sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \
S是第二类斯特林数
***
首先你要把这个组合计数肝出来,~~于是我去翻了一波《组合数学》~~
*用斯特林数容斥原理推导那个式子可以直接出卷积形式,见下一篇,本篇是分治fft做法*
</br>
###组合计数
**斯特林数** $S(n,i)$表示将n个不同元素划分成i个相同集合非空的方案数
**Bell数** $B(n)=\sum\limits_{i=0}^n S(n,i)$也就是分成任意个相同的集合
有一个递推式
\]
B(n) = \sum_{i=0}^{n-1} \binom{n-1}{n-1-i}B(i) = \sum_{i=0}^{n-1} \binom{n-1}{i}B(i)
考虑和第一个元素在同一个集合的元素有几个,剩下的是子问题
或者这么想,因为每个集合相同,我们规定第一个元素在一个集合后这个集合就不相同了,剩下的元素分入这个不相同的集合或者成为子问题
</br>
$S'(n,i)=S(n,i)*i!$就是**集合不相同**啦,
\]
B'(n) = \sum_{i=1}^n \binom{n}{i}B'(n-i)
因为每个集合都不相同,我们没有必要规定第一个元素在集合里了,直接枚举第一个集合元素个数就可以了
</br>
然后那个$2^j$可以认为每个集合有两种颜色,枚举当前集合顺便枚举颜色,乘上一个2就行了
令$f(n)=2 \sum\limits_{i=1}^n \binom{n}{i} f(n-i)$,答案就是$\sum_{i=0}^n f(i)$
快速求出f就可以做了,整理一下发现
\]
f(n) = 2 n! \sum_{i=1}^n \frac{1}{i!} \frac{f(n-i)}{(n-i)!}
</br>
###分治fft
和CDQ分治一样,每次用$[l,mid]$更新$[mid+1,r]$
可以发现,$f(i)[mid+1,r]$都是$\frac{f(i)}{i!}[l,mid]$卷上$\frac{1}{i!}[1,r-l]$的结果
我们把两个函数$[l,mid]$和$[1,r-l]$的部分拿出来做卷积,更新$[mid+1,r]$
可以认为先把向量移动了l位
复杂度$O(nlog^2n)$,13560ms,~~貌似别人的分治fft更慢20000ms多~~
</br>
注意初始值$f[0]=1$因为$S(0,0)=1$,以及cdq(0,n)
</br>
###多项式求逆
当然也可以,具体看[51nod这篇讨论](http://www.51nod.com/question/index.html#!questionId=1713)吧
把$f_0 x^0$单独拿出来的思想比较有意思,$A(x)$从0开始,$B(x)$从1开始($B_0 = 0$)
$$A(x) = F_0 x^0 + A(x) B(x)\]
update 2017.5.3 : 发现tls貌似补了一句\(2x e^x\),求这个东西来做也可以,但不如直接处理处B来方便
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N=(1<<18)+5, INF=1e9;
const ll P=998244353, g=3;
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;
}
ll Pow(ll a, ll b) {
ll ans=1;
for(; b; b>>=1, a=a*a%P)
if(b&1) ans=ans*a%P;
return ans;
}
int n, rev[N];
ll inv[N], fac[N], facInv[N];
ll f[N], a[N], b[N];
void dft(ll *a, int n, int flag) {
for(int i=0; i<n; i++) if(i<rev[i]) swap(a[i], a[rev[i]]);
for(int l=2; l<=n; l<<=1) {
int m=l>>1;
ll wn = Pow(g, flag==1 ? (P-1)/l : P-1-(P-1)/l);
for(ll *p=a; p!=a+n; p+=l) {
ll w=1;
for(int k=0; k<m; k++) {
ll t = w*p[k+m];
p[k+m]=(p[k]-t+P)%P;
p[k]=(p[k]+t)%P;
w=w*wn%P;
}
}
}
if(flag==-1) {
ll inv=Pow(n, P-2);
for(int i=0; i<n; i++) a[i]=a[i]*inv%P;
}
}
void cdq(int l, int r) {
if(l==r) return;
int mid=(l+r)>>1;
cdq(l, mid);
int lim=r-l+1, n=1, k=0;
while(n<lim) n<<=1, k++;
for(int i=0; i<n; i++) rev[i] = (rev[i>>1]>>1) | ((i&1)<<(k-1));
for(int i=0; i<n; i++) a[i]=b[i]=0;
for(int i=l; i<=mid; i++) a[i-l] = f[i];
for(int i=0; i<=r-l; i++) b[i] = facInv[i];
dft(a, n, 1); dft(b, n, 1);
for(int i=0; i<n; i++) a[i]=a[i]*b[i]%P;
dft(a, n, -1);
for(int i=mid+1; i<=r; i++) f[i]=(f[i] + 2*a[i-l])%P;
cdq(mid+1, r);
}
int main() {
freopen("in","r",stdin);
n=read();
inv[1]=1; fac[0]=facInv[0]=1;
for(int i=1; i<=n; i++) {
if(i!=1) inv[i] = (P-P/i)*inv[P%i]%P;
fac[i] = fac[i-1]*i%P;
facInv[i] = facInv[i-1]*inv[i]%P;
}
f[0]=1;
cdq(0, n);
ll ans=0;
for(int i=0; i<=n; i++) ans = (ans + f[i]*fac[i]%P)%P;
if(ans<0) ans+=P;
printf("%lld\n", ans);
}
BZOJ 4555: [Tjoi2016&Heoi2016]求和 [分治FFT 组合计数 | 多项式求逆]的更多相关文章
- BZOJ 4555 [Tjoi2016&Heoi2016]求和 ——分治 NTT 多项式求逆
不想多说了,看网上的题解吧,我大概说下思路. 首先考察Stirling的意义,然后求出递推式,变成卷积的形式. 然后发现贡献是一定的,我们可以分治+NTT. 也可以直接求逆(我不会啊啊啊啊啊) #in ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 [FFT 组合计数 容斥原理]
4555: [Tjoi2016&Heoi2016]求和 题意:求\[ \sum_{i=0}^n \sum_{j=0}^i S(i,j)\cdot 2^j\cdot j! \\ S是第二类斯特林 ...
- [BZOJ4555][TJOI2016&HEOI2016]求和(分治FFT)
4555: [Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 525 Solved: 418[Sub ...
- bzoj 4555 [Tjoi2016&Heoi2016]求和 NTT 第二类斯特林数 等比数列求和优化
[Tjoi2016&Heoi2016]求和 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 679 Solved: 534[Submit][S ...
- BZOJ 4555 [Tjoi2016&Heoi2016]求和 (多项式求逆)
题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4555 题目大意: 给定 \(S(n,m)\) 表示第二类斯特林数,定义函数 \(f(n ...
- bzoj 4555: [Tjoi2016&Heoi2016]求和【NTT】
暴力推式子推诚卷积形式,但是看好多blog说多项式求逆不知道是啥.. \[ \sum_{i=0}^{n}\sum_{j=0}^{n}S(i,j)*2^j*j! \] \[ S(i,j)=\frac{1 ...
- 洛谷P4721 【模板】分治 FFT(生成函数+多项式求逆)
传送门 我是用多项式求逆做的因为分治FFT看不懂…… upd:分治FFT的看这里 话说这个万恶的生成函数到底是什么东西…… 我们令$F(x)=\sum_{i=0}^\infty f_ix^i,G(x) ...
- [BZOJ 4555][Tjoi2016&Heoi2016]求和
题意 给定 $n$ , 求下式的值: $$ f(n)= \sum_{i=0}^n\sum_{j=0}^i\begin{Bmatrix}i\\ j\end{Bmatrix}\times 2^j\time ...
- BZOJ 4555: [Tjoi2016&Heoi2016]求和 (NTT + 第二类斯特林数)
题意 给你一个数 \(n\) 求这样一个函数的值 : \[\displaystyle f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i} \begin{Bmatrix} i \\ j ...
随机推荐
- IE8兼容border-radius.
我们知道,CSS3新增的很多简洁优美的属性,比如border-radius.box-shadow.border-image.gradients.RGBA...因为这些属性的出现,我们可以很方便的就写会 ...
- JavaScript函数声明提升
首先,JavaScript中函数有两种创建方式,即函数声明.函数表达式两种. 1.函数声明. function boo(){ console.log(123); } boo() 2.函数表达式. va ...
- 如何让低版本IE浏览器支持HTML5标签并为其设置样式
现代的浏览器都支持HTML5,HTML5定义了 8 个新的 HTML 语义元素.所有这些元素都是 块级 元素. 为了能让旧版本的浏览器正确显示这些元素,你可以设置 CSS 的 display 属性值为 ...
- windows平台下python 打包成exe可执行文件
第一步 安装 pyinstaller 命令行下运行:pip install pyinstaller 第二步 打包安装 pyinstaller Test.py 第三步 完成 找到打包目录下dist目录 ...
- POJ 1502 MPI Maelstrom(模板题——Floyd算法)
题目: BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distri ...
- Kafka集群的搭建
Kafka集群的搭建 node1 node2 node3 kafka须用版本(kafka-0.8.2.2),否则不兼容spark1.6 1.启动zookeeper集群node1 node2 ...
- ico图标在谷歌浏览器中如何显示?
http://www.zen-cart.cn/forum/topic266117.html 版主: shaning 发表回复 2 篇帖子 • 分页: 1 / 1 ico图标在谷歌浏览器中如何显示? ...
- CCF系列之窗口(201403-2)
试题编号: 201403-2时间限制: 1.0s 内存限制: 256.0MB 问题描述 在某图形操作系统中,有 N 个窗口,每个窗口都是一个两边与坐标轴分别平行的矩形区域.窗口的边界上的点也属于该窗口 ...
- servlet入门学习之生命周期
一. 什么是Servlet Servlet是用Java语言编写的服务器端小程序,驻留在web服务器中,并在其中运行,扩展了web服务器的动态处理功能. 用java语言编写的java类 在web容器中运 ...
- ntp 时钟同步
注意: 如果你无法和外部网络的时钟同步,请检查UDP端口时候被封.