题意

一个有\(n\)个元素的集合,将其分为任意个非空子集,求方案数。集合之间是无序的,\(\{\{1,2\},\{3\}\}=\{\{3\},\{1,2\}\}\)。


设\(f_n\)表示用\(n\)个元素组成的集合的个数,显然\(f_n=1\)。设\(F(x)\)为\(f\)的指数型生成函数,那么\(F(x)=\sum_{i=1}\frac{x^i}{i!}\),\(F^i(x)\)的第\(n\)位就是\(i\)个元素个数之和为\(n\)的集合组合在一起的方案数。

设\(g_i\)为\(n=i\)时的答案,再设\(G(x)\)为\(g\)的指数型生成函数。枚举划分的集合个数:

\[G(x)=\sum_{i=0}\frac{F^i(x)}{i!}
\]

显然\(F(x)=e^x-1\),那么\(G(x)=e^{e^x-1}\),\(G(x)\)第\(i\)项乘\(i!\)就是\(g_i\)。多项式\(exp\)即可。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define cn const
#define gc getchar()
#define fp(i,a,b) for(rg int i=(a),ed=(b);i<=ed;++i)
#define fb(i,a,b) for(rg int i=(a),ed=(b);i>=ed;--i)
using namespace std;
typedef cn int cint;
il int rd(){
rg int x(0),f(1); rg char c(gc);
while(c<'0'||'9'<c){ if(c=='-') f=-1; c=gc; }
while('0'<=c&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;
return x*f;
}
cint inf=0x3f3f3f3f,maxn=1000010,mod=998244353; int T,n=100000,inv[maxn],fac[maxn],ifac[maxn];
int a[maxn],f[maxn],g[maxn],A[maxn],B[maxn];
int lim=1,l,rev,r[maxn]; il int fpow(int a,int b,int ans=1){
for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;
return ans;
}
il int finv(cint &n){return fpow(n,mod-2);}
cint G=3,invG=finv(G); il void ntt(int *a,cint &f){
fp(i,0,lim-1)if(i<r[i])swap(a[i],a[r[i]]);
for(rg int md=1;md<lim;md<<=1){
rg int len=md<<1,Gn=fpow(f?G:invG,(mod-1)/len);
for(rg int l=0;l<lim;l+=len){
rg int Pow=1;
for(rg int nw=0;nw<md;++nw,Pow=1ll*Pow*Gn%mod){
rg int x=a[l+nw],y=1ll*Pow*a[l+nw+md]%mod;
a[l+nw]=(x+y)%mod,a[l+nw+md]=(x-y+mod)%mod;
}
}
}
} void get_inv(int *a,int *b,int n){
if(n==1){b[0]=finv(a[0]);return;}
get_inv(a,b,n>>1);
fp(i,0,n)B[i]=a[i];
lim=1,l=0; while(lim<=n<<1)lim<<=1,++l; rev=finv(lim);
fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
ntt(B,1),ntt(b,1);
fp(i,0,lim)b[i]=1ll*b[i]*((2-1ll*B[i]*b[i]%mod+mod)%mod)%mod; ntt(b,0);
fp(i,0,n)b[i]=1ll*b[i]*rev%mod; fp(i,n+1,lim)b[i]=0;
fp(i,0,lim)B[i]=0;
} il void get_ln(int *a,int *b,int n){
fp(i,1,n)A[i-1]=1ll*a[i]*i%mod; get_inv(a,b,n);
lim=1,l=0; while(lim<=n<<1)lim<<=1,++l; rev=finv(lim);
fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
ntt(A,1),ntt(b,1);
fp(i,0,lim)b[i]=1ll*b[i]*A[i]%mod; ntt(b,0);
fp(i,0,n)b[i]=1ll*b[i]*rev%mod; fp(i,n+1,lim)b[i]=0;
fp(i,0,lim)A[i]=0;
fb(i,n,1)b[i]=1ll*b[i-1]*inv[i]%mod; b[0]=0;
} void get_exp(int *a,int *f,int n){
if(n==1){f[0]=1;return;}
get_exp(a,f,n>>1),get_ln(f,g,n);
g[0]=(1-g[0]+a[0]+mod)%mod; fp(i,1,n)g[i]=(a[i]-g[i]+mod)%mod;
lim=1,l=0; while(lim<=n<<1)lim<<=1,++l; rev=finv(lim);
fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
ntt(f,1),ntt(g,1);
fp(i,0,lim)f[i]=1ll*f[i]*g[i]%mod; ntt(f,0);
fp(i,0,n)f[i]=1ll*f[i]*rev%mod; fp(i,n+1,lim)f[i]=0;
fp(i,0,lim)g[i]=0;
} int main(){
fac[0]=1; fp(i,1,n)fac[i]=1ll*fac[i-1]*i%mod;
inv[1]=1; fp(i,2,n)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
ifac[0]=1; fp(i,1,n)ifac[i]=1ll*ifac[i-1]*inv[i]%mod; fp(i,1,n)a[i]=ifac[i];
while(lim<=n)lim<<=1; get_exp(a,f,lim); T=rd();
while(T--)n=rd(),printf("%lld\n",1ll*f[n]*fac[n]%mod);
return 0;
}

LuoguP5748 集合划分计数的更多相关文章

  1. [P5748] 集合划分计数 - 生成函数,NTT

    求 \(10^5\) 以内的所有贝尔数:将 \(n\) 个有标号的球划分为若干非空集合的方案数 Solution 非空集合的指数生成函数为 \(F(x)=e^x-1\) 枚举一共用多少个集合,答案就是 ...

  2. CODEVS 2055 集合划分

    [题目描述] 对于从1到N(1<=N<=39)的连续整数集合,划分成两个子集合,使得每个集合的数字之和相等. 举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字 ...

  3. [CODEVS2055]集合划分

    对于从1到N(1<=N<=3)的连续整数集合,划分成两个子集合,使得每个集合的数字之和相等.举个例子,如果N=3,对于{1,2,3}能划分成两个子集合,他们每个的所有数字和是相等的:{3} ...

  4. 集合划分——cf1028D思维题

    非常思维的一道题目,题意很长 给定s1,s2两个集合,s1维护最大值,s2维护最小值,s1的所有元素要比s2小 操作1:往两个集合里的任意一个添加x 操作2:把x从所在的集合里删掉:要求被删的x必须是 ...

  5. Atcoder Grand Contest 038 F - Two Permutations(集合划分模型+最小割)

    洛谷题面传送门 & Atcoder 题面传送门 好久前做的题了--今天偶然想起来要补个题解 首先考虑排列 \(A_i\) 要么等于 \(i\),要么等于 \(P_i\) 这个条件有什么用.我们 ...

  6. N个元素的集合划分成互斥的两个子集的数目

    前面这是寒假听马士兵老师讲的时候积累的语录.......... 1.php是水果刀,java是菜刀,刀法比较多,一年的和三年的区别很大. 2.nanicat连接mysql出现10061是服务没开启,却 ...

  7. P5748-集合划分计数【EGF,多项式exp】

    正题 题目链接:https://www.luogu.com.cn/problem/P5748 题目大意 求将\(n\)的排列分成若干个无序非空集合的方案. 输出答案对\(998244353\)取模. ...

  8. 集合划分状压dp

    给一个 $n$ 个点 $m$ 条边的无向图,每条边有 $p_i$ 的概率消失,求图连通的概率 $n \leq 9$ sol: 我们考虑一个 $dp$ $f_{(i,S)}$ 表示只考虑前 $i$ 条边 ...

  9. BZOJ 2127: happiness(最小割解决集合划分)

    Time Limit: 51 Sec  Memory Limit: 259 MBSubmit: 2350  Solved: 1138[Submit][Status][Discuss] Descript ...

随机推荐

  1. html 08-HTML5详解(二)

    08-HTML5详解(二) #本文主要内容 拖拽 历史 地理位置 全屏 #拖拽 如上图所示,我们可以拖拽博客园网站里的图片和超链接. 在HTML5的规范中,我们可以通过为元素增加 draggable= ...

  2. maven继承父工程统一版本号

    一.建立一个maven工程 pom类型 统一管理依赖以及版本号 子工程不会使用所有的定义的依赖 子工程使用依赖时无需指定版本号 pom.xml <project xmlns="http ...

  3. Python利用openpyxl带格式统计数据(1)- 处理excel数据

    统计数据的随笔写了两篇了,再来一篇,这是第三篇,前面第一篇是用xlwt写excel数据,第二篇是用xlwt写mysql数据.先贴要处理的数据截图: 再贴最终要求的统计格式截图: 第三贴代码: 1 '' ...

  4. python初学者-鸡兔同笼简单算法

    鸡兔同笼问题.假设共有鸡.兔30只,脚90只.求鸡.兔各有多少只 使用for循环快速解决鸡兔同笼问题 for ji in range(0,31): if 2*ji+(30-ji)*4==90: pri ...

  5. Ubuntu不能直接从windows复制粘贴文件或文字

    终端输入: apt-get autoremove open-vm-tools sudo apt-get install open-vm-tools-desktop 然后重启电脑就可以了. 参考链接:h ...

  6. [LeetCode]148. Sort List链表归并排序

    要求时间复杂度O(nlogn),空间复杂度O(1),采用归并排序 传统的归并排序空间复杂度是O(n),原因是要用一个数组表示合并后的数组,但是这里用链表表示有序链表合并后的链表,由于链表空间复杂度是O ...

  7. PLA-机器学习基石2

    转自:http://blog.csdn.net/u013455341/article/details/46747343 在<机器学习基石>这门课里面也进入了第一讲的内容,这次学习到的是Pe ...

  8. Android驱动学习-app调用内核驱动过程(驱动框架回顾)

    考研已经过去了,android驱动的学习也断了半年多了,现在重新捡起来学习,回顾一下Android驱动的大体框架. Android系统的核心是java,其有一个David虚拟机.Android-app ...

  9. Kubernetes官方java客户端之一:准备

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  10. 什么是CDN?哪些是流行的jQuery CDN?使用CDN有什么好处?

    内容传送网络或内容分发网络(CDN)是部署在因特网上的多个数据中心的大型分布式服务器系统.CDN的目标是为具有高可 用性和高性能的最终用户提供内容. 有3个流行的jQuery CDN:谷歌,微软jQu ...