zoukankan      html  css  js  c++  java
  • 《算法竞赛进阶指南》0x38概率与数学期望 Rainbow

    题目链接:https://www.acwing.com/problem/content/218/

    题目给出n个数,要求求从中任意取出一个区间的数求异或和、or和、and和的数学期望。当每个数只有0和1的时候是容易求的,此时只需要把这个int数分解成二进制数对每一位进行求解即可。

    其中异或和的计算中,c1是从r-1开始向前扫描的[l,r-1]段有偶数个1的l取值的集合的大小,c2的定义与 c1相似,只是是奇数个1.如果扫描到当前的数是0,那么只需要保证c1++,如果当前的数是1的话就需要交换c1和c2并且c2的数量++。

    代码:

    #include<iostream>
    #include<cstdio>
    using namespace std;
    const int maxn = 100010;
    int a[maxn],b[maxn];
    int n;
    double ansxor,ansor,ansand;
    void Rainbow(int k){//对每个数的第k位进行处理 
        int last[2]={0,0},c1=0,c2=0;//last表示上一个0/1在哪个给定的数的第k位出现 
        double w=(double)(1<<k)/n/n; 
        for(int i=1;i<=n;i++){
            b[i]=((a[i]>>k)&1);
            if(b[i]){//区间长度为1的情况 
                ansxor+=w;
                ansand+=w;
                ansor+=w;
            }
            //区间长度不为1的情况 
            if(!b[i]){
                ansor+=w*last[1]*2;
                ansxor+=w*c2*2;
            }else{
                ansand+=(i-last[0]-1)*w*2;
                ansor+=w*(i-1)*2;
                ansxor+=w*c1*2;
            }
            //为下一位左右右端点的情况计算新的c1,c2 
            c1++; 
            if(b[i])swap(c1,c2);
            last[b[i]]=i;
        }
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=0;i<31;i++)Rainbow(i);//1e9数据之内最多有31位
        printf("%.3lf %.3lf %.3lf
    ",ansxor,ansand,ansor);
        return 0; 
    } 
  • 相关阅读:
    周五笔记
    python2.0代码重构为3.0一日记
    小白使用Bert跑分类模型
    andrew ng 深度学习 网易云课堂课程
    andrew ng machine learning week9 异常检测和推荐系统
    解决端口占用问题
    postgresqlmysql删除数据表中字段的回车和换行
    echarts常用的属性修改
    后端返回文件流,用blog方式下载 type 值
    antD vue 遇到的一些问题处理
  • 原文地址:https://www.cnblogs.com/randy-lo/p/13288441.html
Copyright © 2011-2022 走看看