题意: 求所有有序对一直除以 2 2 2 直至为奇数后的值的和。
需要发现一个性质,设 f i f_i fi 表示所有能被 2 i 2^i 2i 整除的和,则 f i + 1 − f i f_{i + 1} - f_i fi+1−fi 表示恰好有 i i i 个因子 2 2 2 的和,那么对于这些和,对答案的贡献就是 f i 2 i \dfrac{f_i}{2^i} 2ifi。
因此我们对于按位考虑,对于第 i i i 位,在遍历至 a j a_j aj 时设 s u m a j sum_{a_j} sumaj 表示在它之后的与其互补的数的和, c n t a j cnt_{a_j} cntaj 表示与其互补的数的个数(此处互补的定义是与 a j a_j aj 相加可以被 2 i 2^i 2i 整除,用 ∗ a j ^*a_j ∗aj 表示)。因此从后往前遍历即可得到 f i = ∑ j = 1 n a j × c n t ∗ a j + s u m ∗ a j f_i = \sum \limits_{j = 1}^n a_j \times cnt_{^*a_j} + sum_{^*a_j} fi=j=1∑naj×cnt∗aj+sum∗aj。
代码如下:
for (int i = 0;i <= 25;++i)
{
int p = 1 << i;
for (int j = n;j;--j)
{
++cnt[a[j] % p];
sum[a[j] % p] += a[j];
f[i] += a[j] * cnt[(p - a[j] % p) % p] + sum[(p - a[j] % p) % p];
}
for (int j = 1;j <= n;++j) cnt[a[j] % p] = sum[a[j] % p] = 0;
}
for (int i = 0;i < 25;++i) ans += (f[i] - f[i + 1]) / (1 << i);
1204

被折叠的 条评论
为什么被折叠?



