首页 > 代码库 > bzoj4036[HAOI2015]set 按位或

bzoj4036[HAOI2015]set 按位或

Vfk的集合幂级数论文的例题….随机集合并为全集的期望集合数….这篇题解里的东西基本来自vfk的论文.

首先根据期望的线性性,我们把需要走第1步的概率(一定为1)加上需要走第2步的概率(等于走了第一步之后没有得到全集的概率)加上需要走第3步的概率(等于走了两步之后没有得到全集的概率)….一直加到需要走正无穷步的概率就是期望的步数.那么走了x步之后没有得到全集的概率等于走了x步之后得到不是全集的集合的概率之和.那么我们用集合并卷积定义乘法,把给出的概率视作集合幂级数,求集合幂级数的等比数列之和,把除了全集一项的其他项的值加起来就是答案.

集合幂级数的莫比乌斯变换和莫比乌斯反演:从f[]数组求得F[]数组,使得F[x]=sigma{f[j],j&x==j},F[]称作f[]的莫比乌斯变换,f[]称作F[]的莫比乌斯反演.

集合幂级数的等比数列之和不容易直接求,但集合幂级数的莫比乌斯变换的等比数列之和易求,而且集合幂级数的莫比乌斯变换的等比数列之和就是集合幂级数的等比数列之和的莫比乌斯变换,我们莫比乌斯反演回来就得到了集合幂级数的等比数列之和.

那么我们只要能快速求解集合幂级数的莫比乌斯反演和莫比乌斯变换,问题就解决了.

Vfk论文里的快速莫比乌斯变换(FMT):

for(i=0;i<n;++i)
    for(j=0;j<(1<<n);++j)
        if(j&(1<<i))f[j]+=f[j^(1<<i)];

 

快速莫比乌斯反演:

for(i=0;i<n;++i)
    for(j=0;j<(1<<n);++j){
        if(j&(1<<i))f[j]-=f[j^(1<<i)];

两个过程基本相同,快速反演相当于把快速变换的过程倒了过来.

我们直接在f数组上运算,算法结束后f数组中保存原数组的莫比乌斯变换或莫比乌斯反演.

莫比乌斯变换其实相当于n维前缀和,莫比乌斯反演其实相当于n维差分.也可以用DP来理解。集合并卷积还算是集合幂级数中比较良心易懂的东西.

智商着急现场:http://liu-runda.blog.uoj.ac/blog/2360

bzoj4036[HAOI2015]set 按位或