集合幂级数学习笔记
推荐学习:陈昕阳同志在APIO2025讲课课件《集合幂级数在子图计数问题上的应用》
认识集合幂级数
集合幂级数是近年来兴起的信息学考点,24年25年中,集合幂级数出现了三次,分别是联合省选2024D2T2重塑时光、联合省选2025D2T2岁月、NOI2025D2T2集合。
笔者以为(其实是瞎猜的),集合幂级数在2014年第一次在我国信息学奥林匹克出现。
吕凯风同志曾在集训队论文中提到集合幂级数。
当我们遇到有关集合的问题时,我们可能需要运用集合幂级数。
集合幂级数的基本操作
泰勒展开式:\(exp(x)=e^x=\sum_{i=0}\frac{x^i}{i!}\)。
我们对做集合幂级数\(A\)做\(exp\)要保证\(A(空集)=0\)。同理,我们对做集合幂级数\(A\)做\(ln\)要保证\(A(空集)=1\)。这个是和我们搞FFT、NTT的多项式一样的。
用以下代码求集合幂级数 \(exp\)、\(ln\) 和逆。
void Jhmjss(long long *a,const int zsc,const int syj,const short Q)
{
for(int w=0;w<zsc;w++) h1[ypx[w]][w]=a[w];
for(int i=0;i<=syj;i++) FWTxor(h1[i],zsc);
long long *h0;h0=new long long[syj+1];
for(int w=0;w<zsc;w++)
{
for(int i=0;i<=syj;i++) h0[i]=h1[i][w];
if(Q==1) Jhmexp(h0,syj);
else if(Q==2) Jhmlnn(h0,syj);
else if(Q==3) Jhmnii(h0,syj);
else puts("wrong");
for(int i=0;i<=syj;i++) h1[i][w]=h0[i];
}
for(int i=0;i<=syj;i++) FWTxor(h1[i],zsc);
for(int w=0;w<zsc;w++) a[w]=h1[ypx[w]][w]*Nw2[syj]%mod;
for(int i=0;i<=syj;i++) for(int w=0;w<zsc;w++) h1[i][w]=0;
return;
}
void FWTxor(long long *a,const int zsc)
{
for(int mid=1;mid<zsc;mid<<=1)
{
for(int j=0;j<zsc;j+=(mid<<1)) for(int k=0;k<mid;k++)
{
long long x=a[j+k],y=a[j+k+mid];
a[j+k]=x+y;if(a[j+k]>=mod) a[j+k]-=mod;
a[j+k+mid]=x-y;if(a[j+k+mid]<0) a[j+k+mid]+=mod;
}
}
return;
}
void Jhmexp(long long *a,const int syj)
{
long long *b;b=new long long[syj+1];
for(int i=1;i<=syj;i++) b[i]=0;b[0]=1;
for(int i=1;i<=syj;i++)
{
for(int j=1;j<=i;j++) b[i]=(b[i]+b[i-j]*a[j]%mod*j)%mod;
b[i]=b[i]*NY[i]%mod;
}
for(int i=0;i<=syj;i++) a[i]=b[i];
return;
}
void Jhmlnn(long long *a,const int syj)
{
long long *b;b=new long long[syj+1];
for(int i=0;i<=syj;i++) b[i]=0;
for(int i=1;i<=syj;i++)
{
for(int j=1;j<i;j++)
b[i]=(b[i]+b[j]*a[i-j]%mod*j)%mod;
b[i]=(a[i]-b[i]*NY[i])%mod;
if(b[i]<0) b[i]+=mod;
}
for(int i=0;i<=syj;i++) a[i]=b[i];
return;
}
void Jhmnii(long long *a,const int syj)
{
long long *b;b=new long long[syj+1];
for(int i=1;i<=syj;i++) b[i]=0;b[0]=my_pow(a[0],mod-2);
for(int i=1;i<=syj;i++)
{
for(int j=1;j<=i;j++) b[i]=(b[i]+a[j]*b[i-j])%mod;
b[i]=(-b[i]*b[0])%mod;if(b[i]<0) b[i]+=mod;
}
for(int i=0;i<=syj;i++) a[i]=b[i];
return;
}
其中,\(Nw2_x\)表示\(2^{-x}\),\(NY_i\)表示\(i^{-1}\)。
\(exp\):\(B_n=\frac{1}{n}\sum_{i=1}^{n}A_iB_{n-i}i,B_0=1\)
\(ln\):\(B_n=-\frac{1}{n}\sum_{i=1}^{n-1}B_iA_{n-i}i,B_0=0\)
求逆:\(B_n=-\frac{1}{n}\sum_{i=1}^{n}A_iB_{n-i},B_0=\frac{1}{A_0}\)
练习题
FWT和FMT及简单应用
P4717 【模板】快速莫比乌斯 / 沃尔什变换 (FMT / FWT)
P3175 [HAOI2015] 按位或
四个模板题
这些题目的题解讲的比我好
P12230 集合幂级数 exp
P12231 集合幂级数 ln
P12232 集合幂级数求逆
P6097 【模板】子集卷积
集合幂级数在子图计数上的应用
主要根据陈昕阳同志在APIO2025讲课课件《集合幂级数在子图计数问题上的应用》整理
连通性限制
数连通子图
给定n个点m条边的简单无向图G=(V,E),求有多少边集E′满足E′⊆E且(V,E′)是连通图。答案对998244353取模。
数连通二分子图
ARC105F Lights Out on Connected Graph
可以做到 \(n=20\)。
练习题
QOJ5411 CTT2020 杏仁
简要题意:对于给定的源点\(s\),汇点\(t\),称一张有向图为杏仁,当且仅当这张有向图的边集可以被划分为若干条从s到t的路径,且这组划分满足所有路径的点集仅在\(s\),\(t\)两点相交(设划分出\(k\)条路径的点集分别为\(S_{1\sim k}\),应满足∀\(i\neq j,S_i\cap S_j = {s,t}\))。给定\(n\)个点\(m\)条边(可能有重边自环)的有向图\(G=(V,E)\)以及固定的源汇点\(s\),\(t\),回答\(q\)次询问:每次询问给出点u,询问G有多少杏仁子图满足其包含边\(s→u\),答案对998244353取模。对于\(G=(V,E)\),称\(G′=(V′,E′)\)是\(G\)的杏仁子图,当且仅当\(G′\)是杏仁,且V′⊆V,E′⊆E\(,\)V′$内无孤立点。数据规模:\(2≤n≤22,0≤q≤n\)。
强连通性、可达性、无环限制
数DAG定向
CF1193A
技巧:DAG容斥
数强连通子图
笔者认为,数强连通子图非常重要,最好对所写的代码标准化处理。
for(int w=1;w<(1<<n);w++)
{
int jie=0;
while(!(w&(1<<jie))) jie++;
for(int x=(w-1)&w;x;x=(x-1)&w)
{
if(x&(1<<jie)) c2[w]=(c2[w]-c3[w^x]*c1[x])%mod;
}
if(c2[w]<0) c2[w]+=mod;
c1[w]=w2[b4[w]]-c2[w];
for(int x=(w-1)&w;x;x=(x-1)&w)
{
c1[w]=(c1[w]-w2[b4[w^x]]*w2[b3[p0[w]+p0[x]]]%mod*c3[x])%mod;
}
if(c1[w]<0) c1[w]+=mod;
c3[w]=c1[w]+c2[w];
if(c3[w]>=mod) c3[w]-=mod;
}
其中,\(b1_{w,i}\)表示从点集\(w\)连向点\(i\)的有向边数量,\(b2_{i,w}\)表示从点\(i\)连向点集\(w\)的有向边数量,\(b4_{w}\)表示起点和终点都在点集\(w\)的有向边数量。
放进数组\(b3\)的是一个三进制数,记\(w\)为三进制下为\(1\)的位集合,\(x\)为三进制下为\(2\)的位集合,显然这里\(w\)和\(x\)无交,那么\(b3\)的这个位置表示起点在点集\(w\)且终点在点集\(x\)的有向边数量。
\(c1_w\)即为点集\(w\)的强连通数量,\(c2\)和\(c3\)是辅助数组。
练习题
联合省选2024D2T2重塑时光
联合省选2025D2T2岁月
(笔者只会性质)
双连通性限制
点双连通-连通变换
马耀华同志的题解在这个题目的讨论里。
讲得很好,很好理解。
边双连通-连通变换
陈昕阳同志有讲,马耀华同志在点双连通生成子图计数的题解中也有提到。
暂时还没有完全理解。
数仙人掌
感觉这个放在双连通性限制目录下有点奇怪。
类似于求点双。\(O(2^nn^3)\)。
例题:交通管制
(笔者不会)
练习题题解
连通性限制:QOJ5411 CTT2020 杏仁
时间复杂度\(O(2^{n-2}n^2+2^{n-2}q)\),空间复杂度\(O(2^{n-2}n+n^2)\)。
浙公网安备 33010602011771号