1893: 985的数学难题
Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 147 Solved: 30
Submit Status Web Board
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 <cstdio>
#include <cstring>
#define M 100010
#define N 18 //控制位数,太大会超时
#define LL long long
int map[M][N], a[M], n;
int judge() //把所有的二进制的一都存在数组里面
{
for(int i=1; i<=n; i++)
{
for(int j=0; j<N; j++)
{
if(a[i] & (1 << j))
{
map[i][j] += map[i-1][j] + 1; //表示1 ---> i 个数二进制的第 j+1 位有多少个 1 都是从上一步推过来的
}
else
{
map[i][j] = map[i-1][j];
}
}
}
}
LL add(int i, int j)
{
LL ans = 0;
for(int k=0; k<N; k++)
{
if(a[i] & (1 << k)) //1<<k就是创建一个1, 移动到第k位
{
ans += (LL)(map[j][k] - map[i][k] + j - i) * (1 << k);//这里如果没有(LL)会超内存
}
else
{
ans += (LL)(map[j][k] - map[i][k]) * (1 << k);
}
}
return ans;
}
LL yihuo(int i, int j)
{
LL ans = 0;
for(int k=0; k<N; k++)
{
if(a[i] & (1 << k)) //判断a[i] 二进制的 第 k+1 位是不是 1
{
ans += (LL)(j - i - map[j][k] + map[i][k]) * (1 << k);
}
else
{
ans += (LL)(map[j][k] - map[i][k]) * (1 << k);
}
}
return ans;
}
LL yu(int i, int j)
{
LL ans = 0;
for(int k=0; k<N; k++)
{
if(a[i] & (1 << k))
{
ans += (LL)(map[j][k] - map[i][k]) * (1 << k);
}
}
return ans;
}
LL huo(int i, int j)
{
LL ans = 0;
for(int k=0; k<N; k++)
{
if(a[i] & (1 << k))
{
ans += (LL)(j - i) * (1 << k);
}
else
{
ans += (LL)(map[j][k] - map[i][k]) * (1 << k);
}
}
return ans;
}
int main()
{
int t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
memset(map, 0, sizeof(map));
for(int i=1; i<=n; i++)
{
scanf("%d", &a[i]);
}
judge();
LL ans = 0;
for(int i=1; i<n; i++)
{
ans += add(i, n) + yihuo(i, n) + yu(i, n) + huo(i, n);
}
printf("%lld\n", ans);
}
return 0;
}