• CH3801Rainbow的信号


    Description

    Freda发明了传呼机之后,rainbow进一步改进了传呼机发送信息所使用的信号。由于现在是数字、信息时代,rainbow发明的信号用N个自然数表示。为了避免两个人的对话被大坏蛋VariantF偷听T_T,rainbow把对话分成A、B、C三部分,分别用a、b、c三个密加密码。现在Freda接到了rainbow的信息,她的首要工作就是解密。Freda了解到,这三部分的密码计算方式如下:
    在1~N这N个数中,等概率地选取两个数l、r,如果l>r,则交换l、r。把信号中的第l个数到第r个数取出来,构成一个数列P。
    A部分对话的密码是数列P的xor和的数学期望值。xor和就是数列P中各个数异或之后得到的数; xor和的期望就是对于所有可能选取的l、r,所得到的数列的xor和的平均数。
    B部分对话的密码是数列P的and和的期望,定义类似于xor和。
    C部分对话的密码是数列P的or和的期望,定义类似于xor和。
    
    代码改自紫书
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    int a[1000001], b[1000001], n;
    double ansxor, ansand, ansor;
    
    inline void solve(int k){
    	register int last[2]={0,0},c1=0,c2=0;
    	for(register int i=1;i<=n;i++) {//处理b[i]和length=1的情况
    		b[i]=((a[i]>>k)&1);//取出每个数的第k位
    		if(b[i]){//当且仅当b[i]!=0时才会有贡献
    			ansxor+=(1<<k)*1.0/n/n;
    			ansand+=(1<<k)*1.0/n/n;
    			ansor+=(1<<k)*1.0/n/n;
    		}
    	}
    	for(register int i=1;i<=n;i++){//处理length>=2的情况
    		if(b[i]==0){
    			ansor+=(1<<k)*2.0/n/n*last[1];
    			ansxor+=(1<<k)*2.0/n/n*c2;
    		}else{
    			ansand+=(1<<k)*2.0/n/n*(i-1-last[0]);//(i-1)-(last[0]+1)+1
    			ansor+=(1<<k)*2.0/n/n*(i-1);
    			ansxor+=(1<<k)*2.0/n/n*c1;
    		}
    		c1++;
    		if(b[i])swap(c1,c2);
    		last[b[i]]=i;
    	}
    }
    int main(){
    	cin>>n;
    	for(register int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(register int i=0;i<31;i++)solve(i);
    	printf("%.3f %.3f %.3f
    ",ansxor,ansand,ansor);
    }
    
  • 相关阅读:
    格式化Format使用
    ASP.NET几种清除页面缓存的方法
    repeater中分页aspnetpager是遇到的问题
    利用正则表达式去掉html代码
    ASP.NET母版页中调用内容页的方法和web用户控件调用.aspx页面里的方法
    PHP常用代码大全
    用 JA Transmenu 模块做多级弹出菜单
    简单的 "改变" joomla 后台administrator目录
    数据库设计中的14个技巧
    Joomla模板制作教程(转)
  • 原文地址:https://www.cnblogs.com/lqhsr/p/10808065.html
Copyright © 2020-2023  润新知