题目描述
这是一个简单的异或和的和的问题。
给你N个数字,求ΣAi XOR Aj(i<j)对10^9+7的余数。其中XOR表示亦或。
输入
第一行一个整数N。
第二行N个整数表示数组A。
保证2<=N<=3*10^5,0<=Ai<2^60。
输出
输出一个整数表示你的答案。
样例输入
样例输入1:
3
1 2 3
样例输入2:
10
3 1 4 1 5 9 2 6 5 3
样例输入3:
10
3 14 159 2653 58979 323846 2643383 27950288 419716939 9375105820
样例输出
样例输出1:
6
样例解释1:
(1 XOR 2)+(1 XOR 3)+(2 XOR 3)=3+2+1=6
样例输出2:
237
样例输出3:
103715602
题解
可知数据为long long 类型,容易超时,故暴力肯定超时
根据异或的性质,我们可以求出所有数据两两异或后每一位的数,最后转成十进制数
#include<cstdio>
#define mod 1000000007
int n;
long long f[300005],ans=0;
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%lld",&f[i]);
for (int k=0;k<=60;k++)
{
int x=0,y=0,cnt=0;
for (int i=1;i<=n;i++) if (f[i]&(1ll<<k)) ++x;else ++y;
for (int i=1;i<=n;i++) if (f[i]&(1ll<<k)) cnt=(cnt+y)%mod,--x;
else cnt=(cnt+x)%mod,--y;
ans=(ans+(1ll<<k)%mod*cnt%mod)%mod;
}
printf("%lld\n",ans);
return 0;
}
其中 1ll为 long long 类型的1;
我们所有数据都从二进制表示的最后一位倒着计算每一位异或后的结果
for (int i=1;i<=n;i++) if (f[i]&(1ll<<k)) ++x;else ++y;
这行代码负责记录倒数第i位上 1和0 的个数x和y;
for (int i=1;i<=n;i++) if (f[i]&(1ll<<k)) cnt=(cnt+y)%mod,--x;
else cnt=(cnt+x)%mod,--y;
负责计算该位上的结果 1还是0;
ans=(ans+(1ll<<k)%mod*cnt%mod)%mod;
最后转成2进制ans
完毕