最近碰见了一些互异关系容斥的题目,而这类题目往往要配合集合幂级数的一些技术使用,所以简单记记。

内容很杂,行文很乱,作者水平很低,酌情观看。

互异关系容斥

思想其实很基本,应用范围其实很广。

原论文

思想就是对于 \(x_i\neq x_j\) 这样的限制,经典对于限制的子集容斥是钦定违反 \(S\) 中的限制,容斥系数为 \((-1)^{|S|}\)。

那么违反 \(x_i\neq x_j\) 相当于 \(x_i=x_j\),这是一个相等关系,可以将图划分成若干个等价类进行考虑。

互异关系容斥的第一个思想便是:对于每一个等价类,求出它边集的容斥系数之和。

举个例子,假设我们现在对一张完全图 \(K_n\) 的边集施加了容斥。这样相当于这张图被划分成了若干个等价类。对于大小为 \(m\) 的等价类,我们实际上要求的是所有使等价类联通的边集 \(E\subseteq E_{K_m}\) 的 \((-1)^{|E|}\) 之和。

设 \(f_n=\sum_{E\subseteq E_{K_n}} (-1)^{|E|}=[n=1]\),求个 \(\ln\) 就是联通图的系数:

\[g_n=f_n-\sum_{i=1}^n {n-1 \choose i-1} g_i f_{n-i}
\]

归纳知:\(g_n=(-1)^{n-1} (n-1)!\)。

互异关系容斥的第二个思想就是:对于 \(\bigoplus_{i=1}^n x_i=c\) 这样一种限制,如果 \(x_i\) 关于 \(\oplus\) 运算逆元总是存在且唯一(如模素数的加法群),那么我们如果知道了 \(x_1,x_2\dots x_{n-1}\) 就可以唯一确定一个 \(x_n\)。

那么如果不限制 \(x_i\) 互不相同,满足上述限制的个数就是 \(V^{n-1}\),\(V\) 是 \(x_i\) 的值域大小。

限制 \(x_i\) 互不相同可以看看周子衡大佬的论文是如何解决的。

集合幂级数

了解甚浅……只会一些基本的应用。

首先 \(\text{FWT}\) 应用了线性变换关于各维独立的性质,相当于给每一维乘上了一个 \(2\times 2\) 的矩阵。

我们不仅要知道 \(\text{FWT}\) 对于每一维分别的影响,更要知道做完 \(\text{FWT}\) 后整体的结果是怎样的。

具体地:

\[\text{or-FWT}:g_S=\sum_{T\subseteq S} f_T\\
\text{or-IFWT}:g_S=\sum_{T\subseteq S} (-1)^{|S|-|T|} f_T\\
\text{and-FWT}:g_S=\sum_{S\subseteq T} f_T\\
\text{and-IFWT}:g_S=\sum_{S\subseteq T} (-1)^{|S|-|T|} f_T\\
\text{xor-FWT}:g_S=\sum_{S\subseteq T} (-1)^{|S \cap T|} f_T\\
\text{xor-IFWT}:g_S=\frac{1}{2^n}\sum_{S\subseteq T} (-1)^{|S \cap T|} f_T\\
\]

然后子集卷积定义了 \(n+1\) 个占位幂级数。我们对占位幂级数 \(\text{or-FWT}\) 后的结果可以上各种各样的多项式操作。这里的操作由于都不是复杂度瓶颈所以都可以 \(O(n^2)\) 递推。

\(\ln:g_n=f_n-\frac{1}{n}\sum_{i=1}^{n-1} g_i i f_{n-i}\)。需要保证常数项为 \(1\)。

\(\exp:g_n=\frac{1}{n}\sum_{i=1}^{n} f_i i g_{n-i}\)。需要保证常数项为 \(0\)。

\(\mathrm{inv}:g_n=\frac{1-\sum_{i=0}^{n-1} g_i f_{n-i}}{f_0}\)。需要保证常数项存在逆。

注意!对于 \(F^n\) 不要多项式 \(\ln\) 再 \(\exp\),可以直接递推:

\[G=F^n\Rightarrow G'=nF^{n-1} F' \Rightarrow FG'=nF^n F'\Rightarrow FG'=nGF'
\]

比较系数即可递推。\(n\) 可以是有理数,顺便实现了多项式开根。

[HNOI2011] 卡农

求从 \(1,2,3\dots 2^k-1\) 中选 \(n\) 个数满足异或和为 \(0\) 的方案数。

递推做法前人之述备矣。我们考虑上点科技。

做法一:互异关系容斥

具体参考原论文。

原论文里给的第二道例题允许空集。这里要求不含空集,我们可以上点容斥,利用递推/推式子容斥掉空集。

不过这样做感觉有点复杂?还不如直接递推。

做法二:集合幂级数

发现如果定义形式幂级数乘法为异或卷积,答案就是:\(\prod_{S\neq \emptyset}(1+x^S y)\) 的 \(y^n\) 项系数。

我们对于每一个式子手动 \(\text{xor-FWT}\) 后点乘起来然后手动 \(\text{xor-IFWT}\)。

具体参见 qwaszx 题解

QOJ 5827 异或图

给定一张图,\(\forall (u,v)\in E,b_u\neq b_v\),\(b_i\in [1,a_i]\),求 \(\mathrm{xor}_{i=1}^n b_i=c\) 的方案数。\(n\leq 15\)。

如果没有互异关系,那么可以直接数位 \(\text{DP}\)。具体地,如果有一位上界是 \(1\) 但填了 \(0\) 那么后面的位任选,相当于去掉了异或和的限制,可以直接算方案数。

现在对互异关系上容斥,求出每一个点子集的容斥系数,集合幂级数求个 \(\ln\) 就得到了点子集是连通块的容斥系数。

发现大小为奇数的连通块相当于替换成一个数的限制 \(\min_{i\in S} a_i\),偶数连通块直接给答案乘上 \(\min_{i\in S} a_i + 1\)。

于是设 \(f_{S,T}\) 表示奇数联通块的限制下标为 \(T\),\(\text{DP}\) 即可。

复杂度上界是 \(O(4^n)\),但跑不满,然而写 unordered_map 会被卡常,用 vector 存一下就可以了。

#include <cstdio>
#include <vector>
using namespace std;
template<typename T>
T read(){
char c=getchar();T x=0;
while(c<48||c>57) c=getchar();
do x=(x<<1)+(x<<3)+(c^48),c=getchar();
while(c>=48&&c<=57);
return x;
}
const int N=33,S=1<<15,LG=63,P=998244353;
typedef long long ll;
int n,m,rk;ll c;
ll a[N],lis[N];
bool ban[S];
int coe[S],pos[S];
void inc(int &x,int v){if((x+=v)>=P) x-=P;}
void dec(int &x,int v){if((x-=v)<0) x+=P;}
vector< pair<int,int> > f[S];
int tmp[S];
int suf[N][2];
bool sta[LG],vis[S];
int stk[S],tp;
void upd(int x,int val){
if(!vis[x]) vis[stk[tp++]=x]=1;
inc(tmp[x],val);
}
int main(){
n=read<int>();m=read<int>();c=read<ll>();
for(int i=0;i<n;++i) a[i]=read<ll>();
for(int i=0;i<m;++i){
int u=read<int>()-1,v=read<int>()-1;
ban[(1<<u)|(1<<v)]=1;
}
for(int i=1;i<(1<<n);i<<=1)
for(int j=0;j<(1<<n);j+=(i<<1))
for(int k=j;k<(j|i);++k) ban[k|i]|=ban[k];
for(int s=1;s<(1<<n);++s){
int lb=__builtin_ctz(s);
int _s=s^(1<<lb);
pos[s]=lb;
if(_s&&a[pos[_s]]<a[lb]) pos[s]=pos[_s];
coe[s]=!ban[s];
for(int _t=_s;;_t=(_t-1)&_s){
int t=_t|(1<<lb);
if(t!=s&&!ban[s^t]) dec(coe[s],coe[t]);
if(!_t) break;
}
}
f[0].emplace_back(0,1);
for(int s=1;s<(1<<n);++s){
int lb=__builtin_ctz(s);
int _s=s^(1<<lb);
tp=0;
for(int _t=_s;;_t=(_t-1)&_s){
int t=_t|(1<<lb);
for(auto [x,val]:f[s^t])
if(__builtin_parity(t)) upd(x|(1<<pos[t]),(ll)coe[t]*val%P);
else upd(x,(a[pos[t]]+1)%P*val%P*coe[t]%P);
if(!_t) break;
}
f[s].resize(tp);
for(int i=0;i<tp;++i){
int x=stk[i];
f[s][i]=make_pair(x,tmp[x]);
tmp[x]=0;vis[x]=0;
}
}
int res=0;
for(auto [s,val]:f[(1<<n)-1]){
rk=0;
for(int i=0;i<n;++i)
if(s>>i&1) lis[rk++]=a[i];
int ans=0;
for(int t=59;~t;--t){
suf[rk][0]=1;suf[rk][1]=0;
for(int i=rk-1;~i;--i){
sta[i]=lis[i]>>t&1;
if(sta[i]){
lis[i]^=(1ll<<t);
suf[i][0]=((1ll<<t)%P*suf[i+1][0]+(lis[i]+1)%P*suf[i+1][1])%P;
suf[i][1]=((1ll<<t)%P*suf[i+1][1]+(lis[i]+1)%P*suf[i+1][0])%P;
}
else{
suf[i][0]=(lis[i]+1)%P*suf[i+1][0]%P;
suf[i][1]=(lis[i]+1)%P*suf[i+1][1]%P;
}
}
int par=(c>>t&1),cur=1;
for(int i=0;i<rk;++i){
if(sta[i]){
ans=(ans+(ll)cur*suf[i+1][par])%P;
par^=1;
}
cur=(lis[i]+1)%P*cur%P;
}
if(par) break;
if(!t) ++ans;
}
res=(res+(ll)ans*val)%P;
}
printf("%d\n",res);
return 0;
}

互异关系容斥&集合幂级数小记的更多相关文章

  1. LOJ575. 「LibreOJ NOI Round #2」不等关系 [容斥,分治FFT]

    LOJ 思路 发现既有大于又有小于比较难办,使用容斥,把大于改成任意减去小于的. 于是最后的串就长成这样:<<?<?<??<<<?<.我们把一段连续的& ...

  2. hdu 4135 a到b的范围中多少数与n互质(容斥)

    Co-prime 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4135 input The first line on input contains ...

  3. 【bzoj4671】异或图(容斥+斯特林反演+线性基)

    传送门 题意: 给出\(s,s\leq 60\)张图,每张图都有\(n,n\leq 10\)个点. 现在问有多少个图的子集,满足这些图的边"异或"起来后,这张图为连通图. 思路: ...

  4. 51 nod 1439 互质对(Moblus容斥)

    1439 互质对 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 有n个数字,a[1],a[2],…,a[n].有一个集合,刚开 ...

  5. BZOJ4671 异或图(容斥+线性基)

    题意 定义两个结点数相同的图 \(G_1\) 与图 \(G_2\) 的异或为一个新的图 \(G\) ,其中如果 \((u, v)\) 在 \(G_1\) 与 \(G_2\) 中的出现次数之和为 \(1 ...

  6. BZOJ 4671 异或图 | 线性基 容斥 DFS

    题面 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 (u, v) 在 G 中 ...

  7. 51Nod 1439:互质对(用莫比乌斯来容斥)

    有n个数字,a11,a22,…,ann.有一个集合,刚开始集合为空.然后有一种操作每次向集合中加入一个数字或者删除一个数字.每次操作给出一个下标x(1 ≤ x ≤ n),如果axx已经在集合中,那么就 ...

  8. bzoj 4671 异或图——容斥+斯特林反演+线性基

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4671 考虑计算不是连通图的方案,乘上容斥系数来进行容斥. 可以枚举子集划分(复杂度是O(Be ...

  9. bzoj 2839 集合计数 容斥\广义容斥

    LINK:集合计数 容斥简单题 却引出我对广义容斥的深思. 一直以来我都不理解广义容斥是为什么 在什么情况下使用. 给一张图: 这张图想要表达的意思就是这道题目的意思 而求的东西也和题目一致. 特点: ...

  10. bzoj2839: 集合计数 容斥+组合

    2839: 集合计数 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 523  Solved: 287[Submit][Status][Discuss] ...

随机推荐

  1. Deepin20安装pip3和Pydev插件

    1. 安装jdk(见前面) 2. 安装eclipse(见前面) 3. Deepin20里已经有python3.7.3和python2.7.16,我们可以直接使用3.7.3,也是默认的python3.还 ...

  2. centos安装k8s

    1.确保每台机器上有docker http://get.daocloud.io/#install-docker 2.关闭 每台机器上的swap,selinux swapoff -a setenforc ...

  3. Exception processing template "index": An error happened during template rendering

    问题所在 brandList[0].brandId出错,要不就改正,要不就把他删了,注释也会报错.

  4. SQL SERVER 2014 双机热备操作流程-数据库双向同步 (第一篇:发布)

    需求:需要两个数据库双向同步,即A数据库变动,B及时更新.B数据库变动,A及时更新.思路:利用SQL Server的发布和订阅功能进行同步,在A数据库进行发布<合并发布>,在B数据库进行订 ...

  5. 转载:VMware Esxi开通SSH功能

    转载:https://www.cnblogs.com/dsl146/p/13739953.html ESXi 5.5是直接安装在物理主机上的一个虚拟机系统,本质上是一个Linux系统.平时可以通过VM ...

  6. LeetCode224 基本计算器

    idea:刚开始是打算分类讨论,建立了数字栈和字符栈,按照传入字符当时两个栈的基本情况分类,结果讨论完之后分类太麻烦,导致分析完了之后漏洞不少.我觉得这道题难点在于括号和负号的处理,一开始将导致计算机 ...

  7. Python gdal读取MODIS遥感影像并结合质量控制QC波段掩膜数据

      本文介绍基于Python中GDAL模块,实现MODIS遥感影像数据的读取.计算,并基于质量控制QC波段进行图像掩膜的方法.   前期的文章Python GDAL读取栅格数据并基于质量评估波段QA对 ...

  8. 什么是RPA?

    RPA是Robotic Process Automation(机器人流程自动化)的简称,是以软件机器人及人工智能为基础的业务过程自动化科技.它让软件机器人自动处理大量重复的.基于规则的工作流程任务,能 ...

  9. 继续Vue的探索

    接上集 上次到了想要利用Vue实现隔行变色的请求,但是由于使用的代码过于"高级"导致无法识别,这就需要利用webpack来解决它! webpack的基本使用 1.首先,在项目中安装 ...

  10. vuex记录状态

    // actions import { queryProductDetailsById } from '../service' /* * 异步 */ export const addAndGetPro ...