P3175 [HAOI2015] 按位或题解

P3175 [HAOI2015] 按位或

题目描述

刚开始你有一个数字 000,每一秒钟你会随机选择一个 [0,2n−1][0,2^n-1][0,2n1] 的数字,与你手上的数字进行或(C++,C 的 |,pascal 的 or)操作。选择数字 iii 的概率是 pip_ipi。保证 0≤pi≤10\leq p_i \leq 10pi1∑pi=1\sum p_i=1pi=1 。问期望多少秒后,你手上的数字变成 2n−12^n-12n1

输入格式

第一行输入 nnn 表示 nnn 个元素,第二行输入 2n2^n2n 个数,第 iii 个数表示选到 i−1i-1i1 的概率。

输出格式

仅输出一个数表示答案,绝对误差或相对误差不超过 10−610^{-6}106 即可算通过。如果无解则要输出 INF

输入输出样例 #1

输入 #1

2
0.25 0.25 0.25 0.25

输出 #1

2.6666666667

说明/提示

对于 100%100\%100% 的数据,n≤20n\leq 20n20

以下为 spj 源代码。

//liuchenrui 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#define AC {fclose(fstd),fclose(fuser);return 0;}
#define WA {fclose(fstd),fclose(fuser);return 1;}
#define PE {fclose(fstd),fclose(fuser);return 5;}
#define eps 1e-6
int main(int const argc, char*const argv[]){
    FILE *fstd,*fuser;
    fstd=fopen(argv[2],"r");
    fuser=fopen(argv[3],"r");
    //fstd=fopen("x1.in","r");
    //fuser=fopen("x2.in","r");
    char s[30],t[30];
    if(fscanf(fuser,"%s",s+1)==-1)WA;
    fscanf(fstd,"%s",t+1);
    if(s[1]=='I' && t[1]=='I')AC;
    if(s[1]=='I' || t[1]=='I')WA;
    double p,q;
    sscanf(s+1,"%lf",&p);
    sscanf(t+1,"%lf",&q);
    if(fabs(p-q)<eps)AC
    else{
        if(fabs(p-q)/q<eps)AC;
        if(fabs(q-p)/q<eps)AC;
        if(fabs(p-q)/p<eps)AC;
        if(fabs(q-p)/p<eps)AC;
    }
    WA;
}

思路

容斥即可。

代码见下

#include<bits/stdc++.h> 
using namespace std;
long long n,m,b[2000006];
double aa[2000006],a[2000006],op=0.00;
const long long mod=998244353;
void or1(double *f,long long x){
    for(int o=2,k=1;o<=n;o*=2,k*=2){
        for(int i=0;i<=n-1;i+=o){
            for(int j=0;j<=k-1;j++){
                f[i+j+k]=(f[i+j+k]+f[i+j]*x);
            }
        }
    }
    return ;
}
int main(){
    cin>>m;
    n=pow(2,m);
    for(int i=0;i<=n-1;i++){
        cin>>aa[i];
        a[i]=aa[i];
        b[i]=b[i/2]+i%2;
    }
    or1(a,1);
    for(int i=1;i<=n-1;i++){
        if(1-a[(n-1)^i]>1e-8){
            if(b[i]%2==1){
                op=(op+1.00/(1-a[(n-1)^i]));
            }
            else{
                op=(op-1.00/(1-a[(n-1)^i]));
            }
        }
    }
    if(op<1e-8){
        cout<<"INF"<<endl;
    }
    else{
        printf("%.12lf\n",op);
    }
	return 0; 	
}
posted @ 2026-02-06 17:05  bz02_2023f2  阅读(1)  评论(0)    收藏  举报  来源