UESTC 84 Binary Operations(算贡献求期望)

来源:互联网 发布:融资毕业论文知乎 编辑:程序博客网 时间:2024/04/30 21:26

题意:给你一个长度n的数列,求出所有区间的and,or,xor的值的期望


题解:这种题直接求比较麻烦,一般位运算的题就是字典树和按位枚举呗,这题就肯定是按位枚举,于是可以求出第i个数字的第j位对以它为区间右端点的贡献。
最后除以区间个数n(n+1)2即可
下面来看and的贡献,_and[i][j]能够贡献的区间个数是需要前面连续多个1,所以找从i开始往前碰到的第一个0的位置
_or[i][j]能够贡献的区间个数是区间内只要有1即可,所以往前找到第一个1出现的位置
_xor[i][j]能够贡献的区间个数是当前到第i位,1的个数是奇数还是偶数,然后找前面1的个数是相反的区间个数(奇数就找偶数,偶数就找奇数)


代码:

#include <map>#include <set>#include <stack>#include <queue>#include <cmath>#include <string>#include <vector>#include <cstdio>#include <cctype>#include <cstring>#include <sstream>#include <cstdlib>#include <iostream>#include <algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;#define   MAX           50005#define   MAXN          6005#define   maxnode       15#define   sigma_size    30#define   lson          l,m,rt<<1#define   rson          m+1,r,rt<<1|1#define   lrt           rt<<1#define   rrt           rt<<1|1#define   middle        int m=(r+l)>>1#define   LL            long long#define   ull           unsigned long long#define   mem(x,v)      memset(x,v,sizeof(x))#define   lowbit(x)     (x&-x)#define   pii           pair<int,int>#define   bits(a)       __builtin_popcount(a)#define   mk            make_pair#define   limit         10000//const int    prime = 999983;const int    INF   = 0x3f3f3f3f;const LL     INFF  = 0x3f3f;const double pi    = acos(-1.0);//const double inf   = 1e18;const double eps   = 1e-8;const LL    mod    = 1e9+7;const ull    mx    = 133333331;/*****************************************************/inline void RI(int &x) {      char c;      while((c=getchar())<'0' || c>'9');      x=c-'0';      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; }/*****************************************************/int a[MAX];LL _and[MAX];LL _or[MAX];LL _xor[MAX];int pre1[MAX];int pre0[MAX];int main(){    int t,kase=0;    cin>>t;    while(t--){        kase++;        printf("Case #%d: ",kase);        int n;        scanf("%d",&n);        for(int i=1;i<=n;i++) RI(a[i]);        LL aa=0,bb=0,cc=0;        for(int i=30;i>=0;i--){            _and[0]=0;            _or[0]=0;            _xor[0]=0;            pre1[0]=0,pre0[0]=0;            int odd=0,even=1;            int num1=0;            for(int j=1;j<=n;j++){                if((a[j]>>i)&1){                    pre1[j]=max(j,pre1[j-1]);                    pre0[j]=pre0[j-1];                    num1++;                }                else pre1[j]=pre1[j-1],pre0[j]=max(j,pre0[j-1]);                if(num1%2) odd++;                else even++;                _and[j]=_and[j-1]+(LL)(j-pre0[j])*(1LL<<i);                _or[j]=_or[j-1]+(LL)pre1[j]*(1LL<<i);                if(num1%2) _xor[j]=_xor[j-1]+(LL)even*(1LL<<i);                else _xor[j]=_xor[j-1]+(LL)odd*(1LL<<i);            }            aa+=_and[n];            bb+=_or[n];            cc+=_xor[n];        }        printf("%.6f %.6f %.6f\n",aa*1.0/n/(n+1)*2,bb*1.0/n/(n+1)*2,cc*1.0/n/(n+1)*2);    }    return 0;}
0 0
原创粉丝点击