[PKUWC2018]随机算法
给定一张图,大小为 (n),边数为 (m)。
现执行一个算法:
- 随机一个排列 (p)
- 然后令 S 为空集,依次考虑排列 (p),对于 (forall i,1le ile n),检查 (Slor p_i) 是否为独立集,如果是则加入 (p_i)
求这个算法的期望正确概率。
( m Sol:)
先考虑一个自动机来识别原算法构成独立集是谁。
我们建 (dp[S]) 数组表示状态 (S) 是否为独立集。
我们先不关注是否是排列的问题,仅考虑依次加入一些元素然后判定上述算法构成的独立集是啥。
考虑加入一个字符之后的转移状态 (Go(S,p)),显然只有两种情况:
- (S o S',S o S)
对于前者意味着自动机上进行了转移,表示加入了一个合法的元素,我们只关注后者,显然后者有两种:一类是加入了原来在 S 中存在的元素,一类是加入了原来不存在的元素。
如果是第一类,那么显然此时在计数时会记重,所以我们忽略它,只考虑第二类。
我们注意到非法的字符读入数量是单调的:假设对于状态 (S) 有字符 (p) 非法,同时 (S') 由 (S) 转移得到,那么显然 (p) 对于 (S') 同样非法,对于每个状态预处理有多少个接受字符是非法的,预处理可以走到终点的状态,问题变成给定一张 DAG,每条边有边权(每条边表示从状态 S 走到状态 S' 会增加多少个非法的元素),记 (k) 为当前经过的边权和,每次走过一条边之后累加 (k) (实质表示有 (k) 个元素),然后每次走过一条边之后可以以任意顺序删除若干个元素,求经过 (max{S}) 条边同时用光边权的方案数。
设 (f_{S,j}) 表示当前到达状态 (S),剩余边权/元素数为 (j) 的方案数即可,转移可以直接 copy dp 数组然后再对内部进行转移,可以简单的做到 (mathcal O(2^ncdot n^2)),预期十分跑不满,所以感觉挺能过的,试了一下发现确实可以过。
然后我们可以优化到 (mathcal O(2^ncdot n))
我们考虑将那个无用的维度 (( ext{指}j)) 压掉,显然在转移某条边的时候,我们只需要保证先放入了 S 中的第一个元素,然后剩余的位置可以直接通过组合计数处理。
具体来说是设这条边上有 (k) 个元素,前面的元素我们都直接填入位置中,那么当前会剩余 (n-|S|-f_S-1),其中 (f_S) 表示非法的字符数量(我们考虑从 S 转移到其他状态),那么方案数就是 (inom{n-|S|-f_S-1}{k})