zzuli 1893 985的数学难题

来源:互联网 发布:rgb转换 算法 编辑:程序博客网 时间:2024/04/30 18:53

1893: 985的数学难题

Time Limit: 2 Sec  Memory Limit: 128 MB
Submit: 178  Solved: 44

SubmitStatusWeb 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
思路:考虑每个二进制位,统计每一位的贡献

把每个数的二进制形式分析一下,找出所有有效的1.

((ans[0][i]) * ans[1][i]) >> 1) * li;      //与运算 

((ans[0][i]) * ans[1][i] + (((ans[1][i]-1) * ant[1][i]) >> 1)) * li;        //或运算   

((ans[1][i]-1) * ant[1][i]) >> 1) * li;       //异或运算  

另外 有 a | b = a & b + a ^ b。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn = 1000000;int num[maxn];long long ans;bool cmp(int a,int b){    return a > b;}int main(){    int t,n;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        ans = 0;        for(int i = 1 ; i <= n ; i++)        {            scanf("%d",&num[i]);            ans += num[i];        }        ans *= (n-1);        sort(num+1,num+n+1,cmp);        long long mul = 1;        long long val;        while(num[1])        {            val = 0;            for(int i = 1 ; i <= n ; i++)            {                if(num[i] == 0)                    break;                if(num[i] & 1)                    val++;                num[i] >>= 1;            }            ans += (((val - 1) * val) >> 1) * mul;  // 与运算            ans += ((n - val) * val + (((val - 1) * val) >> 1)) * mul;//或运算            ans += ((n - val) *val) * mul;//异或运算            mul <<= 1;        }        printf("%lld\n",ans);    }    return 0;}


0 0
原创粉丝点击