弱校联萌十一大决战之背水一战B Binary Operations

Bob has a sequence of N integers. They are so attractive, that Alice begs to have a continued part of it(a continued part here also means a continued subsequence). However, Bob only allows Alice to chose it randomly. Can you give the expectation of the result of the bitwise AND, OR, XOR of all the chosen numbers?

Input


First line of the input is a single integer T(1 <= T <= 50), indicating there are T test cases.

The first line of each test case contains a single number N(1 <= N <= 50000).

The second line contains N integers, indicating the sequence.

All the N integers are fit in [0, 10^9].

Output

For each test case, print "Case #t: a b c" , in which t is the number of the test case starting from 1, a is the expectation of the bitwise AND, b is the expectation of OR and c is the expectation of XOR.

Round the answer to the sixth digit after the decimal point.

Sample Input

3
2
1 2
3
1 2 3
3
2 3 4

Sample Output

Case #1: 1.000000 2.000000 2.000000
Case #2: 1.333333 2.500000 1.666667
Case #3: 1.833333 4.333333 3.666667

Hint

AND is a binary operation, performed on two numbers in binary notation. First, the shorter number is prepended with leading zeroes until both numbers have the same number of digits (in binary). Then, the result is calculated as follows: for each bit where the numbers are both 1 the result has 1 in its binary representation. It has 0 in all other positions.

OR is a binary operation, performed on two numbers in binary notation. First, the shorter number is prepended with leading zeroes until both numbers have the same number of digits (in binary). Then, the result is calculated as follows: for each bit where the numbers are both 0 the result has 0 in its binary representation. It has 1 in all other positions.

XOR is a binary operation, performed on two numbers in binary notation. First, the shorter number is prepended with leading zeroes until both numbers have the same number of digits (in binary). Then, the result is calculated as follows: for each bit where the numbers differ the result has 1 in its binary representation. It has 0 in all other positions.


这个题是这场比赛当中做出来的最难的 ,也是最谈不上是什么算法的 ,非要说有 ,也基本上是DP的递推加滚动数组吧

也是很奇怪为啥跟网上几乎一样的代码 ,网友写的超时了 队友自己写的过了 

分析这个题怎么做吧 题意:n个数的数列 连续子序列的与、或、异或的最终期望 说到期望总想排列组合 ╭(╯^╰)╮酱紫就在正确的道路上越走越远了

都说了是连续的子序列了啊 所以总共也就 n*(n+1)/2个集合 在枚举集合的组成的时候应该想到 假设之前状态是第p~q组成的数下一个加入集合的一定是第q+1个数 而以第q+1个数为结尾的集合很明显有q 个  分析到这里 就成功了三分之一 至少是递推的方式找出来啦

既然都知道了枚举方式  为什么我要分析以第q+1个数为结尾的有多少集合呢  因为我想计算在第q+1个数加进来之后对当前集合的变化 

具体说来 :第q+1个数加入后 每一个二进制位都可能会有变化 而 我们将这些集合当前位出现过几次1记录下来 个数再乘以当前位代表的值就是枚举到q+1这个数时候该位为最终结果所作贡献值 看代码吧  说的好糊涂 总之就是需要对二进制深刻理解

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
const LL maxn=5e4+10;

LL a[maxn],s[maxn];
LL num[35];
double yu,huo,yihuo;
void bitadd(int x){
    int k=0;
    while(x){
        if(x&1) num[k]++;
        x>>=1;
        k++;
    }
}
int main()
{
    LL t,n,ca=1;
    cin>>t;
    while(t--){
        scanf("%lld",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
        }
        LL temp;
        yu=huo=yihuo=0;
        memset(num,0,sizeof(num));
        memset(s,0,sizeof(s));
        for(int i=1;i<=n;i++){
            s[i]=a[i];
            if(i==1) bitadd(a[i]);
            else {
                temp=a[i];
                for(int j=0;j<31;j++){
                   if(temp&(1<<j)) {}
                    else num[j]=0;
                   s[i]+=(num[j]*(1<<j));
                }
                bitadd(a[i]);
            }
            yu+=s[i];
        }
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++){
            s[i]=a[i];
            if(i==1){ bitadd(a[i]); huo+=s[i]; continue ; }
            temp=a[i];
            for(int j=0;j<31;j++){
                if(temp&(1<<j)) num[j]=i-1;
                s[i]+=(num[j]*(1<<j));
            }
            huo+=s[i];
            bitadd(a[i]);
        }
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++){
            s[i]=a[i];
            if(i==1){ bitadd(a[i]); yihuo+=s[i]; continue ; }
            temp=a[i];
            for(int j=0;j<31;j++){
                if(temp&(1<<j)) num[j]=i-1-num[j];
                s[i]+=(num[j]*(1<<j));
            }
            bitadd(a[i]);
            yihuo+=s[i];
        }
        printf("Case #%lld: ",ca++);
        LL length=(n+1)*n/2;
        printf("%.6lf %.6lf %.6lf\n",yu/length,huo/length,yihuo/length);
    }
    return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值