2022春每日一题:Day 34

题目:lowbit求和 (没有找到哪个公开题库有这个题)

题意:求数组中任意一对数的异或和的lowbit的总和。
对于异或,二进制位中两个数相等则为0,反之为1,而且此题是要求lowbit,那我们利用这个,对于一个数字,他第i位二进制位k,则显然跟这个数字二进制前缀相同的数与这个数异或起来都是0,但是第i位二进制位为k^1,则这一定是其中的一个贡献,抓住这一点,就可以以二进制位建trie树,然后解决这个问题。
注意,不开longlong见祖宗,开了longlong还是见祖宗,所以部分开

代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
const int N=1e5+5;
const long long pp=199907210507;
using namespace std;
int n,tot;
long long ret,a[N];
namespace trietree
{
	struct trie
	{
		int son[2];
		long long tag[2];
	}e[N*61];
	void insert(long long x)
	{
		int p=0;
		for(int i=0;i<=60;i++)
		{
			int k=x>>i&1;
			e[p].tag[k]++;
			if(!e[p].son[k])
			    e[p].son[k]=++tot;
			p=e[p].son[k];
		}
	}
	int query(long long x)
	{
		int p=0;
		long long ans=0;
		for(int i=0;i<=60;i++)
		{
			int k=x>>i&1;
			ans=(ans+(1LL<<i)%pp*e[p].tag[k^1]%pp)%pp;
			p=e[p].son[k];
		}
		return ans;
	}
}
using namespace trietree;
signed main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	    scanf("%lld",&a[i]),insert(a[i]);
	for(int i=1;i<=n;i++)
		ret=(query(a[i])+ret)%pp;
	printf("%lld\n",ret);
	return 0;
}

posted @   __honey  阅读(62)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示