位思想例题

Double Sum 2

题意: 求所有有序对一直除以 2 2 2 直至为奇数后的值的和。

需要发现一个性质,设 f i f_i fi 表示所有能被 2 i 2^i 2i 整除的和,则 f i + 1 − f i f_{i + 1} - f_i fi+1fi 表示恰好有 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=1naj×cntaj+sumaj

代码如下:

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);
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值