你可见过一种基于状压的二进制筛法?

这个 trick 的妙,妙到让我愿意为它专门写一篇文章出来。(同时会写在 trick 里面)

基于状压,换成数学的语言,函数的值域是一个集合。比如说叫它 f(S)

然后这个 f 满足一些递推的性质:当我们知道 f(S) 的值的时候,可以顺便知道 f(S) 的值,并且这样的 S 数量之和不会很多。

可以类比一下整数的筛法。在整数的筛法中,(多数是)我们可以由 f(x) 知道 f(xk) 的值(其中 k>1k 为整数),并且这样的 xk 的数量很少,是调和级数。

例题 10.16 B.竞赛图

给你一个竞赛图,求它有多少个诱导子图是强连通的。

我们知道竞赛图强连通分量缩点之后一定是一条链。那么,如果它不是一个强连通的图,那肯定可以划分成两部分 A,B,使得 所有 边都是从 AB 的。

即,如果存在 AB,使得 AB 的所有边都是出边,那 A|B 就没了。

f(S) 表示 S 是否“不是一个强连通分量” (类似质数筛,这么定义是方便初始化)

定义 “筛一遍” S:我们找到 S 中所有点的 出边的交,设为 O(可以预处理);对于 O 的任意子集 TS|T 一定不是强连通图,令 f(S|T)=1

什么样的 S 需要像这样“筛一遍”呢?只有 f(S)=0S 需要来枚举一下这个 T,否则 一定被更小的集合筛过了

就像做质数筛的时候只要用质数去更新筛即可。比如说,我们筛掉 6 的倍数的时候,在筛 2,3 的时候已经包含了这个操作,没必要再做一遍

关于复杂度: 我们发现一个集合 只会被筛到一次。那么我们就按照上面说的模拟,直接筛,时间复杂度就是 O(2n) 的。

代码

posted @   Flandre-Zhu  阅读(107)  评论(4编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示