zoukankan      html  css  js  c++  java
  • 你可见过一种基于状压的二进制筛法?

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

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

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

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

    例题 10.16 B.竞赛图

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

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

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

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

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

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

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

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

    代码

  • 相关阅读:
    树上差分
    循环数组最大子段和(带限制的最大子段和,单调队列优化)
    sprintf函数的用法详解
    VBS基础篇
    VBS基础篇
    VBS基础篇
    VBS基础篇
    VBS基础篇
    Android随笔
    Android随笔
  • 原文地址:https://www.cnblogs.com/LightningUZ/p/13826252.html
Copyright © 2011-2022 走看看