正题

题目链接:https://www.luogu.com.cn/problem/P5748


题目大意

求将\(n\)的排列分成若干个无序非空集合的方案。

输出答案对\(998244353\)取模。

\(1\leq n\leq 10^5,1\leq T\leq 1000\)


解题思路

就是求划分数

分成\(i\)个集合的方案是\((e^x-1)^i\)所以答案的生成函数就是

\[\sum_{i=0}^{\infty}\frac{(e^x-1)^i}{i!}
\]

emmmmmmmmmmm...

怎么看上去这么眼熟,所以

\[\sum_{i=0}^{\infty}\frac{(e^x-1)^i}{i!}=e^{e^x-1}
\]

然后写个多项式exp就好了

时间复杂度\(O(n\log n)\)

到此本题目已经结束了,但是我们可以换一种方式来做

我们知道\(\begin{Bmatrix}n\\m\end{Bmatrix}\)是把\(n\)分成\(m\)个非空集合的方案数

所以这这题其实是在求

\[\sum_{i=1}^n\begin{Bmatrix}n\\i\end{Bmatrix}
\]

这个东西应该也很好做,斯特林数有通项

\[\begin{Bmatrix}n\\m\end{Bmatrix}=\frac{1}{m!}\sum_{k=0}^m(-1)^{m-k}k^n\binom{m}{k}
\]
\[\sum_{i=1}^n\frac{1}{i!}\sum_{j=0}^i(-1)^{i-j}j^n\binom{i}{j}
\]

然后拆开组合数化简一下就是

\[\sum_{i=0}^n\sum_{j=0}^i\frac{j^n}{j!}\times \frac{(-1)^{i-j}}{(i-j)!}
\]

然后卷积就好了。

具体化简过程和P4091-求和很像,这里就不多赘述了。


code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=8e5+10,P=998244353;
ll T,n,f[N],g[N],r[N];
ll t1[N],t2[N],t3[N],t4[N],t5[N],t6[N];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void GetL(ll l){
n=1;while(n<=l)n<<=1;
for(ll i=0;i<n;i++)
r[i]=(r[i>>1]>>1)|((i&1)?(n>>1):0);
return;
}
void NTT(ll *f,ll op){
for(ll i=0;i<n;i++)
if(i<r[i])swap(f[i],f[r[i]]);
for(ll p=2;p<=n;p<<=1){
ll len=p>>1,tmp=power(3,(P-1)/p);
if(op==-1)tmp=power(tmp,P-2);
for(ll k=0;k<n;k+=p){
ll buf=1;
for(ll i=k;i<k+len;i++){
ll tt=f[i+len]*buf%P;
f[i+len]=(f[i]-tt+P)%P;
f[i]=(f[i]+tt)%P;
buf=buf*tmp%P;
}
}
}
if(op==-1){
ll invn=power(n,P-2);
for(ll i=0;i<n;i++)
f[i]=f[i]*invn%P;
}
return;
}
void GetInv(ll *f,ll *g,ll m){
if(m==1){g[0]=power(f[0],P-2);return;}
GetInv(f,g,m>>1);GetL(m);
for(ll i=0;i<m;i++)t1[i]=g[i],t2[i]=f[i];
NTT(t1,1);NTT(t2,1);
for(ll i=0;i<n;i++)
t1[i]=t1[i]*t1[i]%P*t2[i]%P;
NTT(t1,-1);
for(ll i=0;i<m;i++)
g[i]=(2*g[i]-t1[i]+P)%P;
for(ll i=0;i<n;i++)t1[i]=t2[i]=0;
return;
}
void GetD(ll *f,ll *g,ll m){
for(ll i=0;i<m-1;i++)
g[i]=f[i+1]*(i+1)%P;
g[m-1]=0;return;
}
void GetJ(ll *f,ll *g,ll m){
for(ll i=1;i<m;i++)
g[i]=f[i-1]*power(i,P-2)%P;
g[0]=0;return;
}
void GetLn(ll *f,ll *g,ll m){
GetD(f,t3,m);GetInv(f,t4,m);
GetL(m);NTT(t3,1);NTT(t4,1);
for(ll i=0;i<n;i++)t3[i]=t3[i]*t4[i]%P;
NTT(t3,-1);GetJ(t3,g,n);
for(ll i=0;i<n;i++)t3[i]=t4[i]=0;
for(ll i=m;i<n;i++)g[i]=0;
return;
}
void GetExp(ll *f,ll *g,ll m){
if(m==1){g[0]=1;return;}
GetExp(f,g,m>>1);GetLn(g,t5,m);
for(ll i=0;i<m;i++)t6[i]=f[i];
GetL(m);NTT(t5,1);NTT(t6,1);NTT(g,1);
for(ll i=0;i<n;i++)
g[i]=g[i]*(1-t5[i]+t6[i]+P)%P;
NTT(g,-1);for(ll i=m;i<n;i++)g[i]=0;
for(ll i=0;i<n;i++)t5[i]=t6[i]=0;
return;
}
signed main()
{
ll m=1;while(m<=1e5)m<<=1;
f[1]=1;GetExp(f,g,m);
(g[0]+=P-1)%=P;f[1]=0;
GetExp(g,f,m);
for(ll i=1,F=1;i<=m;i++,F=F*i%P)f[i]=f[i]*F%P;
scanf("%lld",&T);
while(T--){
scanf("%lld",&n);
printf("%lld\n",f[n]);
}
return 0;
}

P5748-集合划分计数【EGF,多项式exp】的更多相关文章

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

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

  2. LuoguP5748 集合划分计数

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

  3. 【NOI2019模拟2019.6.27】B (生成函数+整数划分dp|多项式exp)

    Description: \(1<=n,k<=1e5,mod~1e9+7\) 题解: 考虑最经典的排列dp,每次插入第\(i\)大的数,那么可以增加的逆序对个数是\(0-i-1\). 不难 ...

  4. 【WC2019】数树 树形DP 多项式exp

    题目大意 有两棵 \(n\) 个点的树 \(T_1\) 和 \(T_2\). 你要给每个点一个权值吗,要求每个点的权值为 \([1,y]\) 内的整数. 对于一条同时出现在两棵树上的边,这条边的两个端 ...

  5. Gym102028G Shortest Paths on Random Forests 生成函数、多项式Exp

    传送门 神仙题-- 考虑计算三个部分:1.\(n\)个点的森林的数量,这个是期望的分母:2.\(n\)个点的所有森林中存在最短路的点对的最短路径长度之和:3.\(n\)个点的所有路径中存在最短路的点对 ...

  6. 洛谷P4726 【模板】多项式指数函数(多项式exp)

    题意 题目链接 Sol 多项式exp,直接套泰勒展开的公式 \(F(x) = e^{A(x)}\) 求个导\(F'(x) = A(x)\) 我们要求的就是\(G(f(x)) = lnF(x) - A( ...

  7. Luogu4389 付公主的背包(生成函数+多项式exp)

    显然构造出生成函数,对体积v的物品,生成函数为1+xv+x2v+……=1/(1-xv).将所有生成函数乘起来得到的多项式即为答案,设为F(x),即F(x)=1/∏(1-xvi).但这个多项式的项数是Σ ...

  8. 【xsy2978】Product of Roots 生成函数+多项式ln+多项式exp

    题目大意:给你两个多项式$f(x)$和$g(x)$,满足$f(x)=\prod\limits_{i=1}^{n}(a_i+1)$,$g(x)=\prod\limits_{i=1}^{m}(b_i+1) ...

  9. luogu P4726 【模板】多项式指数函数 多项式 exp 牛顿迭代 泰勒展开

    LINK:多项式 exp 做多项式的题 简直在嗑药. 前置只是 泰勒展开 这个东西用于 对于一个函数f(x) 我们不好得到 其在x处的取值. 所以另外设一个函数g(x) 来在x点处无限逼近f(x). ...

随机推荐

  1. SynchronizedMap和ConcurrentHashMap有什么区别

    SynchronizedMap实现上在调用Map的所有方法是,对整个map进行了同步! public V put(K key, V value) { synchronized (mutex) {ret ...

  2. C# prism 框架

    定义Region (RegionManager) 定义Region 的方式有两种,一个是在XMAL界面指定,另一种这是代码当中指定. RegionManager.RegionName(XMAL) Re ...

  3. C#基础知识---动态为类型添加属性

    一.概述 通常情况下,我们是事先在类型中定义好属性的,但有时候,我们需要动态为一个类型添加某些属性,这个时候,我们就需要使用DynamicObject类型了. 二.Demo using System; ...

  4. 入门数据结构与算法,看这一个就够了,知识点+LeetCode实战演练

    本笔记来自拉钩教育300分钟搞定算法面试 算法与数据结构 要掌握一种数据结构,就必须要懂得分析它的优点和缺点. 在考虑是否应当采用一种数据结构去辅助你的算法时,请务必考虑它的优缺点,看看它的缺点是否会 ...

  5. 自定义Listener

    前言 为什么要自定义Listener? 通过自定义,可以在程序启动过程中监听特定事件,再回调处理逻辑. 自定义SpringApplicationRunListener 1.创建自定义SpringApp ...

  6. Qt中QOpengl的QMatrix4x4矩阵作用原理以及使用方法

    1.矩阵具有坐标变换的作用,例如:左乘一个旋转矩阵,实现点的坐标旋转,左乘一个平移矩阵实现,点的平移 2.一个点可以同时串联相乘几个变换矩阵,实现坐标连续变换,根据左乘规则,右边矩阵先作用于点,作用顺 ...

  7. 剑指 Offer 32 - III. 从上到下打印二叉树 III

    剑指 Offer 32 - III. 从上到下打印二叉树 III 请实现一个函数按照之字形顺序打印二叉树,即第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印, ...

  8. ReScript 与 TypeScript,谁是前端圈的“当红辣子鸡”

    摘要: ReScript 和 TypeScript 的出现都是为了更好地使用JavaScript,但两者还是有很大的不同. 本文分享自华为云社区<[云创共驻]ReScript 和 TypeScr ...

  9. .NET 5 支持 Azure Functions OpenAPI 扩展啦

    今年5月,在 Build大会上,Azure FunctionsOpenAPI的功能支持(预览版)正式宣布. 当时,它最高支持 v3 运行时--.NET Core 3.1 版本. 最近,它发布了 .NE ...

  10. java 集合特性面试必备

    collection 集合体系 数据结构栈和队列栈结构 :先进后出队列结构 :先进先出 数据结构之数组和链表数组结构:查询快.增删慢队列结构 :查询慢.增删快 List集合概述有序集合(也称为序列), ...