985的数学难题
Description
985有n个正整数,他想快速知道下面函数的返回值
int a[N+1];
long long Solve() {
int i, j;
long long ans = 0;
for(i = 1; i <= N; i++) {
for(int j = i + 1; j <= N; j++) {
ans += a[i] + a[j] + (a[i] ^ a[j]) + (a[i] | a[j]) + (a[i] & a[j]);
}
}
return ans;
}
注:^表示异或运算。
Input
第一行输入一个整数t,代表有t组测试数据。
每组数据第一行输入一个整数代表元素个数,接下来一行输入n个正整数a[]。
注:1 <= t <= 30,1 <= n,a[] <= 100000。
Output
一个整数代表最后的返回值ans。
Sample Input
2
1
10
2
1 1
Sample Output
0
4
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define K 100011
#define INF 0x3f3f3f
using namespace std;
bool cmp(int a,int b)
{
return a>b;
}
long long pa[K];
int main()
{
int i,j;
int N;
int T;
long long ans;
long long ml;
long long cot;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
ans=0;
for(i=1;i<=N;i++)
{
scanf("%lld",&pa[i]);
ans+=pa[i];
}
ans*=(N-1); //先把和求出,每个数相加时都用到了(N-1)次 ;
sort(pa+1,pa+N+1,cmp);
ml=1; //做为每次尾数更新时的见证
while(pa[1]) //当最大的数小于 1 时跳出循环
{
cot=0; //初始化尾数为 1 的个数
for(i=1;i<=N;i++)
{
if(pa[i]==0) //若a[i]为零,则剩下的数定全为零
break;
if(pa[i]&1) //每次只判断尾数是否为为 1
cot++;
pa[i]>>=1; //更新尾数
}
ans+=(cot*(cot-1)>>1)*ml; //只有当两个数的尾数同时才有贡献,从尾数为1的数里挑出两个,总数为(cot*(n-cot)/2);
ans+=(cot*(N-cot)+(cot*(cot-1)>>1))*ml; //当一个数的尾数为 1 时就有贡献,先从尾数为1和0的数里各挑出一个,然后从尾数为 1 的数里挑出两个
ans+=(cot*(N-cot))*ml; // 只有当尾数不同时才有贡献,从尾数为1和0的个数里各挑出一个,总数为(cot*(n-cot));
ml<<=1; //更新每次 ml 的值,尾数每更新一次,ml左移一位;
}
printf("%lld\n",ans);
}
return 0;
}