zoukankan      html  css  js  c++  java
  • [BZOJ 4036][HAOI2015]按位或

    4036: [HAOI2015]按位或

    Time Limit: 10 Sec  Memory Limit: 256 MBSec  Special Judge
    Submit: 746  Solved: 456
    [Submit][Status][Discuss]

    Description

    刚开始你有一个数字0,每一秒钟你会随机选择一个[0,2^n-1]的数字,与你手上的数字进行或(c++,c的|,pascal
    的or)操作。选择数字i的概率是p[i]。保证0<=p[i]<=1,Σp[i]=1问期望多少秒后,你手上的数字变成2^n-1。

    Input

    第一行输入n表示n个元素,第二行输入2^n个数,第i个数表示选到i-1的概率

     

    Output

    仅输出一个数表示答案,绝对误差或相对误差不超过1e-6即可算通过。如果无解则要输出INF

    Sample Input

    2
    0.25 0.25 0.25 0.25

    Sample Output

    2.6666666667

    HINT

     对于100%的数据,n<=20

    题解

    首先无解非常好判. 非 $0$ 概率值全都或起来如果得不到全集就肯定无解了.

    这题要求期望...考虑期望等于啥...

    每步开始之前, 我们对于非全集的情况都需要继续进行下一步.

    由期望的线性性, 我们可以对于每一步都分开计算.

    而进行完一步之后每种状态的概率要怎么算呢? 显然我们有:

    $$ c_k=sum_{ioperatorname{or}j=k} a_it_j$$

    显然这是一个或运算卷积的形式. 所以对于一步的情况, 我们可以FWT解决.

    但是在这个题目里则可能是无限步, 我们继续来思考.

    因为FWT满足卷积定理, 所以我们有:

    $$ operatorname{FWT}left(sum_{i=0}^infty t^i ight)_k=sum_{i=0}^infty operatorname{FWT}(t)_k^i $$

    而等式右边是个首项为 $1$ 的等比数列求和式, 因为 $operatorname{FWT}(t)_kleq 1$ 所以这个值一定收敛于 $frac 1 {1-operatorname{FWT}(t)_k}$.

    算完 $operatorname{FWT}^{-1}$ 回去求所有非全集下标的和就行了.

    代码实现

    毕姥爷: 从我们都熟悉的FWT开始

     1 #include <bits/stdc++.h>
     2 
     3 const int DWT=1;
     4 const int IDWT=-1;
     5 const int MAXN=(1<<20)+233;
     6 
     7 double a[MAXN];
     8 
     9 void FWT(double*,int,int);
    10 
    11 int main(){
    12     int n;
    13     scanf("%d",&n);
    14     int len=1<<n;
    15     int cur=0;
    16     for(int i=0;i<len;i++){
    17         scanf("%lf",a+i);
    18         if(a[i]>0)
    19             cur|=i;
    20     }
    21     if(cur!=len-1)
    22         puts("INF");
    23     else{
    24         FWT(a,len,DWT);
    25         for(int i=0;i<len;i++)
    26             a[i]=1.0/(1-a[i]);
    27         FWT(a,len,IDWT);
    28         double ans=0;
    29         for(int i=0;i<len-1;i++)
    30             ans+=a[i];
    31         printf("%.10f
    ",ans);
    32     }
    33     return 0;
    34 }
    35 
    36 void FWT(double* a,int len,int opt){
    37     for(int i=1;i<len;i<<=1)
    38         for(int j=0;j<len;j+=i<<1)
    39             for(int k=0;k<i;k++)
    40                 a[j+k+i]+=opt*a[j+k];
    41 }
    BZOJ 4036

    日常图包

  • 相关阅读:
    ACM实用C语言函数
    Java中的数组和方法
    eclipse常用快捷键
    【转载】第十章 五种对称加密算法总结
    【转载】ZooKeeper学习第二期--ZooKeeper安装配置
    【转载】Java垃圾回收机制
    【转载】JVM系列三:JVM参数设置、分析
    【转载】JVM系列二:GC策略&内存申请、对象衰老
    【转载】JVM系列一:JVM内存组成及分配
    java项目性能测试过程记录
  • 原文地址:https://www.cnblogs.com/rvalue/p/10242551.html
Copyright © 2011-2022 走看看