题目
Problem Description
Tmk无聊的时候,拿了n张纸,一张纸写了一个数字,然后把它们丢进了一个箱子里面,然后他在里面抽出了两张纸,然后他想知道这两张纸上的值or起来的期望值是多少
Input
第一行一个整数代表n,
后面 n 个整数表示每个数字。100%的数据 2 <= n <= 1e5, 0 <= Ai < 2^20
Output
p/q表示一个分数,其中p和q互质。
Samples
No. Input Output 1 2
0 00/1 2 3
1 2 33/1
分析
- 或运算是可以每一位分开来算再求和的,那么我们就把这些数每一位分开来,统计一下每位
0
和1
的个数,根据或运算的规则处理答案即可。(关于分数模式,其实得出分子分母后同除以gcd即可) - 下表是每一位的三种情况(设这一位共有
x
个1,y
个0)
数量 | 种类 | 贡献 |
---|---|---|
x*y | 0V1 | 1(*2^i) |
C(x,2) | 0V0 | 0(*2^i) |
C(y,2) | 1V1 | 1(*2^i) |
* 注意每一位的贡献加到总分子时,要乘一下当前位的基数。
程序
#include <cstdio>
long long n,a[30],b[30],up,down,k;
long long gcd(long long b,long long c){
if (c==0) return b;
return gcd(c,b%c);
}
int main(){
scanf("%lld",&n);
for (int i=1,o; i<=n; i++){
scanf("%lld",&o);
for (int j=0; j<=25; j++)
if (o&(1<<j)) a[j]++; else b[j]++;
}
for (long long i=0,o=1; i<=25; i++,o<<=1){
long long x=a[i],y=b[i];
up+=(x*y+x*(x-1)/2)*o;
}
down=n*(n-1)/2;
if (down==0) down=1;
k=gcd(up,down);
up/=k;
down/=k;
printf("%lld",up);printf("/");printf("%lld",down);
}