985的数学难题

1893: 985的数学难题

Time Limit: 2 Sec  Memory Limit: 128 MB
    Submit: 140  Solved: 28

SubmitStatusWeb BoardDescription
  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
HINT

Source
hpu

SubmitStatusWeb Board

对于加法可以每个数相加乘n-1就好了至于其他的计算出每一位做的贡献最后相加 详细的直接看代码好了

#include<cstdio>
#include<algorithm>
using namespace std;
bool cmp(int a,int b){
    return a>b;
}
long long a[100010];
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        int n; int i=0;
        scanf("%d",&n);
        long long sum=0;
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            sum+=a[i];
        }
        sum*=(n-1);  //每个数加了n-1次 
        long long ml=1;
        long long ans=0;
        sort(a+1,a+1+n,cmp);
        while( a[1] ){
            ans = 0;
            for( i=1 ; i<=n ; i++)
            {
                if(a[i]==0)
                    break;
                if(a[i]&1)
                    ans++; //计算出末尾有多少在某一位 末尾有多少的 1 
                a[i] >>= 1;
            }
            sum += ( ans * (ans-1) >> 1 ) * ml;  
            // 计算与运算 从 ans 个 1 中选出两个因为全是 1 才加1 可贡献C( 2,ans ); 
            sum += ( ( ans * ( n-ans ) ) + ( ans * ( ans-1 )  >> 1 ) ) * ml;
            // 或运算对这一位的贡献有0 n-ans 个有 1 ans个 从中选出一个零或1 可以贡献一个1 可贡献ans*(n-ans) 
            // 有ans 个1 从中选出来两也可以贡献一个1  可贡献C( 2,ans )  
            // 两种情况相加即可; 
            sum += ( ans * ( n - ans ) ) * ml;
            // 异或中只有0 和 1 才可以贡献一个 1 贡献 ans*(n-ans)个1 ;
            ml <<= 1;//注意每一位都要乘 2的位数平方 
        }
        printf("%lld\n",sum);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值