[FMT 莫比乌斯变换 子集和变换] BZOJ 4036 [HAOI2015]按位或

来源:互联网 发布:sftp命令指定端口 编辑:程序博客网 时间:2024/05/19 14:52

vfk的论文题 看过组合数学 这个习称子集和变换的东西好像叫莫比乌斯变换? 那么这种变换就叫快速莫比乌斯变换 FMT? 大雾
开始推柿子
U表示全集 2n1
fi,S 表示 i 秒当前集合为 S 的概率
gi,S为其莫比乌斯变换 gi,S=xSfi,x
这样 gi,S=(g1,S)i 很好求 也很方便可以搞出其反变换

fi,S=xS(1)|S||x|gi,x

那么
Ans=======i=01fi,Ui=0fi,Ui=0xU(1)|U||x|gi,xxU(1)|U||x|i=0gi,xxU(1)|U||x|i=0(g1,x)ixU,xU(1)|U||x|i=0(g1,x)ixU,xU(1)|U||x|1g1,x1

注意判无解

#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;const int N=2000005;int n,m,cnt[N];double p[N];int main(){  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  scanf("%d",&n); m=1<<n;  for (int i=0;i<m;i++) scanf("%lf",p+i);  for (int i=0;i<n;i++)    for (int j=0;j<m;j++)      if (j>>i&1)    p[j]+=p[j^(1<<i)],cnt[j]++;  for (int i=0;i<m-1;i++)    if (p[i]>=1-1e-8)      return printf("INF\n"),0;  double Ans=0;  for (int i=0;i<m-1;i++)    if ((n-cnt[i])&1)      Ans-=1/(p[i]-1);    else      Ans+=1/(p[i]-1);  printf("%.10lf\n",Ans);  return 0;}
0 0
原创粉丝点击