容斥原理

n 个奖项,获得 S 中的奖项的人数为 g(S) ,求获得至少一个奖项的人数。( 不妨认为g()=0

S(1)|S|1g(S)

记容斥系数为 f(|S|),那么对于 i[0,n] 应该有:

j=1i(ij)f(j)=[i1]

f(i)=(1)i1 恰好满足。


错排问题:

f(i) 为至少有 i 个位置不满足的容斥系数

i=0nf(i)(ni)(ni)!

j=0i(ij)f(j)=[i=0]

f(i)=(1)i

变式:如果 k 个位置满足错排有 ak 的贡献,求所有排列贡献和。

j=0i(ij)f(j)=ai

可以递推计算 f

这就是一般化的容斥


快速计算 f

  1. 打表找规律

j=0i(ij)f(j)=aij=0i1(ij)!f(j)j!=aii!

然后就可以多项式求逆做了。


条件的使用

T1 Emiya 家的饭

si=j=1mai,j

dpi,j,k :前 i 个方法,第 p 种食材选 j 个,其他食材选 k

dpi,j,k=dpi1,j,k1ai,p+dpi1,j1,k(siai,p)+dpi1,j,k

满足要求的状态为 j>k , 所以只需知道 j,k 相对大小,复杂度为 O(n2m)

T2

考虑容斥,枚举不被覆盖的格子的集合,对于剩余能放车的格子方案数为 2

同一列的格子联通,那么记选出的格子所在列构成的集合为 S,这些列是无法放置車的。

现在我们先枚举 S,然后再容斥。

此时可以对每一个行极大连通块独立考虑。具体的,对于一个含有 l 列 , 其中 p 列在 S 中的行,枚举这一行上的 p 个位置有哪一些位置选择了不覆盖,有两种情况:

  • 没有位置不覆盖,剩下的 lp 个位置方案任意。

  • 存在至少一个位置不覆盖,那么这一行不能放车。

但这样计算会有问题,因为无法确定选出的点是否对应 S,即 S 中可能存在若干列未选出不覆盖的点。

那么再次容斥,我们更改 S 的定义为不选車的列,并枚举未选出不覆盖点的列的集合 T(TS)。记该行有 q 列在 T 中。

总贡献即为:

2lp+i=1pq(1)i(pqi)=2lp[pq]

再把所有行的贡献乘起来,意义显然。


一个行的贡献只与 l,p,q 有关,那么将原图划分成如下图形,使同颜色的行贡献相同:

这不就是小根笛卡尔树嘛!!!

fu,i,j 表示以 u 为根的子树,有 i 列在 S 中,有 j 列在 T 中的贡献。

进一步,我们只需知道 [p=q] ,那么第三维可以改为是否存在一列在 S 中却不在 T 中。

转移时枚举当前节点对应的列的选择情况即可。

时间复杂度 O(n2logn)

T3

有一个 n×m 的矩阵,填入 [0,m] 中的数并满足:

  • ai,j<ai,j+1

  • ai,j<ai1,j+1

求方案数。 1n,m106

每一行用 m+1 个数构成长度为 m 的上升序列,只需确定没有填的数就可以知道序列。

那么记 fi,j 表示填完前 i 行,第 i 行未填的数为 j 的方案数,有:

fi,j=k=0j+1fi1,k

fi,j={fi1,0+fi1,1j=0fi,j1+fi1,j+1j0

问题转化为从 (0,0) 走到 P(n+m+1,n) ,且不经过直线 l1:y=x+1l2:y=x(m+2) 的方案数

将路径按经过直线顺序分类,并删去重复经过的部分。

所有不合法路径均可以分类为 1212...2121...

先考虑 1212...,即先经过 l1

  • 1 为结尾 21 为结尾 +121 为结尾 2121 为结尾 ...

  • 12 为结尾 212 为结尾 + 以 1212 为结尾 21212 为结尾

注意到将 Pl1 翻折后得到 P , OP 的结尾一定为 112,将 Pl2 翻折得到 P, OP 的结尾一定为 21212

那么我们不断翻折 P 即可,相信大家都知道关于直线 y=x+b 的对称点为 (y0b,x0+b)

终止状态为 P(x,y) 不在第一象限,x,y正半轴内,因为此时会向左、下走。

每次翻折与对称轴的距离会增加 1,那么只会有 O(n) 次操作。

状态的简并

T4

首先 minmax 容斥得到:

E(max(S))=TS(1)|T|1E(min(T))

AS=iSai

d=AUAT ,表示选到 T 中元素的期望次数。

再考虑如何求 E(min(T)),一个转化是:

E(min(T))=dk0P(min(T)>k)

k 轮(均选中 T 中元素)没结束的情况是:所有数的和为 k 且每个数小于对应的 bi ,概率即为:

ci=k,ci<bi(aiAT)cik!ci!

将每一位的贡献提出来,这样就可以按位计算:

k!ATkci=k,ci<biaicici!


fi,j 表示前 i 个元素,c 的和为 j 的贡献,有:

fi,j=l=0min(bi1,j)fi1,jlailATll!

这样我们得到了 O(2nn2m2) 的暴力


E(max(S))=TS(1)|T|1AUATk0k!ATkci=k,ci<biaicici!

E(max(S))=AUk0k!TS(1)|T|1ATk+1ci=k,ci<biaicici!

前面系数有关的量只有 k,AT,|T|,全部压进状态里:

fi,0/1,j,k: 前 i 个数,选中元素个数的奇偶,选中的元素的 a 的和为 j , c=k 的贡献。

fi,0/1,j,k=fi1,0/1,j,k+l=0min(bi1,k)fi1,1/0,jai,klaill!

答案即为:

E(max(S))=AUk0k!j=1S1jk+1(fn,1,j,kfn,0,j,k)

注意到容斥系数的改变为 -1,可以直接将第二维丢掉。

优化状态

T5

fu,i,S 表示子树 u 内的点,u 对应的点为 i,子树内对应的点的集合为 S 的方案数。

枚举子集转移,复杂度 O(n33n)


如果去掉 S,那么编号可能重复,考虑容斥,枚举所有点对应的点的集合。

j=in(niji)f(j)=[i=n]

可得: f(i)=(1)ni ,直接枚举 S 再 dp 即可。

复杂度 O(2nn3)

容斥系数的处理

T6

先将 n! 唯一分解。

考虑到 ai 相同时 bi 无序,ai 不同时 bi 有序,那么直接看作 bi 有序,最后答案除上 cnt[ai]!

由于 m 不大,尝试划分为若干集合,且钦定每个集合的 bi 相同。

第一部分:容斥系数

令大小为 i 的集合的容斥系数为 fi

一个划分 T 为若干集合的集合 ({S1...Sk}),定义它的容斥系数为集合的容斥系数之积,记为 gT

那么一个划分被统计的贡献为:

i=1kT|SigT

只需满足:

T|SigT=[Si=1]

fn+i=1n1(n1i1)fi(T|SigT)=[n=1]fn+i=1n1(n1i1)fi[ni=1]=[n=1]fn=[n=1](n1)fn1


第二部分:方案数

将同一个集合的 ai 相加得到 Ai

每个质因子可以独立计算,相当于完全背包。

总时间复杂度 O(Bell(n)nm)

注意到方案数只与 |Si|Ai 有关,可以用一个状压 dp 合并方案。

大概是 map 套 set,为了卡常可以使用 hash 比较

这样的方案数大概是划分数级别?

posted @   chihik  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示