UESTC - 1041 Hug the princess(位运算&转换)好题

34 篇文章 0 订阅
12 篇文章 0 订阅
UESTC - 1041
Time Limit:                                                        1000MS                        Memory Limit: 65535KB 64bit IO Format:                            %lld & %llu                       

Status

Description

There is a sequence with n elements. Assuming they are a1,a2,,an.

Please calculate the following expession.

1i<jn(aiaj)+(ai|aj)+(ai&aj)

In the expression above, ^|& is bit operation. If you don’t know bit operation, you can visit

http://en.wikipedia.org/wiki/Bitwise_operation

to get some useful information.

Input

The first line contains a single integer n, which is the size of the sequence.

The second line contains n integers, the ith integer ai is the ith element of the sequence.

1n100000,0ai100000000

Output

Print the answer in one line.

Sample Input

2
1 2

Sample Output

6

Hint

Because the answer is so large, please use long long instead of int. Correspondingly, please use %lld instead of %d to scanf and printf.

Large input. You may get Time Limit Exceeded if you use “cin” to get the input. So “scanf” is suggested.

Likewise, you are supposed to use “printf” instead of “cout”.

Source

The 13th UESTC Programming Contest Preliminary
//题意:
给你n个数,让求 1i<jn(aiaj)+(ai|aj)+(ai&aj)
//思路:
队友的想法太机智了,先用个二维数组存放每个位上的值的和,然后在每个位进行计算。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 1e5 + 100;
int num[MAXN][35];
int a[35];
int p[MAXN];
typedef long long LL;
int main()
{
	int n;
	while(~scanf("%d", &n))
	{
		int x;
		memset(num, 0, sizeof(num));
		for(int i = 1; i <= n; i++)
		{
			scanf("%d", &x);
			for(int j = 0; j < 33; j++)
			{
				num[i][j] = num[i - 1][j] + x % 2;
				x = x / 2;
			}
		}
		LL ans = 0;
		for(int i = 1; i <= n; i++)
		{
			for(int j = 0; j < 33; j++)
			{
				a[j] = num[i][j] - num[i - 1][j];
			}
			for(int j = 0; j < 33; j++)
			{
				int cnt = 0;
				if(a[j])
				{
					cnt += (i - 1 - num[i - 1][j]);//异或值 
					cnt += i - 1;				   //或值 
					cnt += num[i - 1][j];		   //非值 
				}
				else
				{
					cnt += num[i - 1][j];
					cnt += num[i - 1][j];
				}
				ans += (LL)cnt * (1 << j);//得到对应位上的值后再向右移动对应的位数 
			}
		}
		printf("%lld\n", ans);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值