ch3801 Rainbow的信号

关于计算期望的题,具体解法书上已经说的很清楚了

有一个值得注意的事项,就是我们枚举每一位的时候,应该选择从最低位往最高位枚举

否则最终答案会出错,主要是因为浮点数计算出的问题,因为懒得测试,但根据数值书上学的可能原因应该是计算过程后期所加的数很小,两者数量级相差太大,导致小数被吃掉

因为测试数据最终答案相差不大,其他原因不知道,以后要注意

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<queue>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<ctime>
#include<ctype.h>
#include<stdlib.h>
#include<bitset>
#include<algorithm>
#include<assert.h>
#include<numeric> //accumulate
#define endl "\n"
#define fi first
#define se second
#define FOR(i,s,t) for(int i=(s);i<=(t);++i)
#define mem(a,b) memset(a,b,sizeof(a))
#define rush() int MYTESENUM;scanf("%lld",&MYTESENUM);while(MYTESENUM--)
#define debug(x) printf("%d\n",x)
using namespace std;
const int maxn=100000+5;
int n;
int a[maxn],b[maxn],last[2];
double ans_xor,ans_or,ans_and;
int c1,c2;
inline void solve(int k)
{
    mem(last,0);
    c1=c2=0;
    for(int i=1;i<=n;i++)
    {
        b[i]=a[i]>>k&1;
        if(b[i])
        {
            ans_xor+=1.0*(1<<k)/n/n;
            ans_and+=1.0*(1<<k)/n/n;
            ans_or+=1.0*(1<<k)/n/n;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(b[i])
        {
            ans_and+=2.0*(1<<k)/n/n*(i-last[0]-1);
            ans_or+=2.0*(1<<k)/n/n*(i-1);
        }
        else
        {
            ans_or+=2.0*(1<<k)/n/n*last[1];
        }
        ans_xor+=2.0*(1<<k)/n/n*(b[i]?c1:c2);
        c1++;
        if(b[i])
            swap(c1,c2);
        last[b[i]]=i;
    }
}


int main()
{
    cin.tie(0);
    cout.tie(0);
    //ios_base::sync_with_stdio(0);
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=0;i<=30;i++)
    {
        solve(i);
    }
    printf("%.3f %.3f %.3f",ans_xor,ans_and,ans_or);


}

 

posted on 2019-05-05 15:26  欣崽  阅读(226)  评论(0)    收藏  举报

导航