牛客练习赛60 A 大吉大利(位运算)

题目描述

给定 n n n 个整数,依次为 a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an
∑ i = 1 n ∑ j = 1 n ( a i & a j ) \sum_{i = 1}^n\sum_{j = 1}^n(a_i\&a_j) i=1nj=1n(ai&aj) KaTeX parse error: Expected 'EOF', got '&' at position 4: “\&&̲” 是二进制的与运算符。

输入描述:

第一行一个整数 n . n. n.
第二行 n n n 个整数 a i a_i ai.

输出描述:

一个整数表示上述求和式的答案.

示例1

输入

5
1 2 3 4 5

输出

33

思路:

& \& & 的规则是同 1 1 1 1 1 1
以样例为例,将每个数字转换成二进制,

001
010
011
100
101
可以发现,每个数字的1都所在的列的1进行了一遍“&”运算
比如以第三行为例:
1
0
1
0
1
则第一个1与所有的1进行“&”运算完后得到3,第二个与所有的1进行“&”运算后再得到3…
这时候,规律已经很明显了,当行数字所有的“&”运算结果加起来就是1的数目的平方!

就是 4 ∗ 2 2 + 4 ∗ 2 1 + 9 ∗ 2 0 = 33 4 * 2^2 + 4 * 2^1 + 9 * 2^0=33 422+421+920=33

AC代码:

const int N = 1e5 + 10;
ll n, m, x;
ll a[N];
ll maxn, cnt, ans;

ll max(ll a, ll b)
{
	return a > b ? a : b;
}

int main()
{
	sd(n);
	rep(i, 1, n)
	{
		cnt = 0;
		sld(x);
		while (x)
		{
			++cnt;
			if (x & 1)
				a[cnt]++;
			x >>= 1;
		}
		maxn = max(cnt, maxn);
	}
	ans = 0;
	rep(i, 1, maxn)
		ans += (a[i] * a[i]) << (i - 1);
	pld(ans);
	return 0;
}

你可能感兴趣的:(牛客)