BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

时间:2023-02-13 15:40:28

http://www.lydsy.com/JudgeOnline/problem.php?id=4036

http://blog.csdn.net/lych_cys/article/details/50898726

http://blog.csdn.net/qq_21995319/article/details/49800999

for(int i=1;i<=1;i++)

  for(int j=1;j<=1;j++)

    f[i○j]=a[i]*b[j];

当○为按位或时,这种运算就称为集合并卷积。(为按位异或时,运算就称为集合对称差卷积)

写本题最好看一下2015年集训队论文最后一篇 吕凯风的《集合幂函数的性质与应用及快速算法》,有这道题的详细解法,也相对更清晰一些(毕竟符号位置什么的都很清楚)。

其实就是推出公式后进行莫比乌斯变换避免无限的无法计算,然后莫比乌斯反演(容斥定理)推出来答案。

其实,讲真。。我还是不大懂。。当做模型记一下可以么QAQ。

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

BZOJ 4036: [HAOI2015]按位或 集合幂函数 莫比乌斯变换 莫比乌斯反演

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps=1e-;
int n;
double p[<<]={};
int num[<<]={};
inline double mabs(double x){
return x>?x:-x;
}
int main(){
//freopen("a.in","r",stdin);
scanf("%d",&n);
int mx=<<n;
for(int i=;i<mx;i++)scanf("%lf",&p[i]);
for(int i=;i<mx;i<<=)
for(int j=i;j<mx;j++)
if(j&i){p[j]+=p[j-i];num[j]++;}
int z=;
for(int i=;i<mx-;i++){
if(mabs(p[i]-1.0)<eps){z=;break;}
}
if(z)printf("INF\n");
else{
double ans=;
for(int i=;i<mx-;i++){
if((n-num[i])&)ans+=1.0/(1.0-p[i]);
else ans-=1.0/(1.0-p[i]);
}printf("%.10f\n",ans);
}
return ;
}