ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Present CodeForces - 1322B

2021-06-09 03:02:32  阅读:262  来源: 互联网

标签:cnt include logs int 1322B CodeForces 位为 Present 2k


原题链接
想到了按位计算,然后就没有然后了(.)
思路:
  以样例2为例,ans = 2是因为(i,j)和在第二位上为1的序对有奇数个,那么怎么计算奇数个呢?(本蒟蒻卡这了).能够影响第i位的和是否为1的只有1~i位的数字,我们对每个a[i]%2i = b[i],对于每个b[i],我们需要找到与它的和第i位为1的个数.
  注意这里不能简单的考虑为b[i]在第k位为0,找第k位为1的个数,因为存在进位.所以只能考虑和,每个b[i]的取值范围在[0,2k-1],那么b[i]+b[j]的取值范围是[0,2k+1-2].第k位为1的b[i]+b[j]的取值范围是[2k-1,2k-1],[2k+2k-1,2k+1-2],确定了b[i]后,b[j]的范围就求出来了,然后二分找即可.

  一开始没想出来怎么去重,结果发现限定二分范围就行了.

Code

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 400010,M =40; 
int n,a[N],b[N];
LL logs[M];
int get(int s,int n)
{
	int l = 0,r = n;
	while(l<r)
	{
		int mid = l+r+1>>1;
		if(b[mid]<=s) l = mid;
		else r = mid-1;
	}
	return r;
}
int main()
{
	scanf("%d",&n);
	int ans = 0;
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	b[0] = -1e9;
	for(int i=0;i<M;i++) logs[i] = 1ll<<i;
	for(int i=0;i<32;i++)
	{
		int k = i+1,cnt=0;
		for(int j=1;j<=n;j++) b[j] = a[j]%logs[k];
		sort(b+1,b+n+1);
		for(int j=1;j<=n;j++)
		{
			int c = logs[k-1]-b[j]-1,d=logs[k]-1-b[j];
			int l = get(c,j-1);
			int r=get(d,j-1);
			if(l>r) continue;
			cnt+=r-l;
			c = logs[k]+logs[k-1]-b[j]-1,d=logs[k+1]-2-b[j];
			l = get(c,j-1),r = get(d,j-1);
			if(l>r) continue;
			cnt+=r-l;
		}
		if(cnt&1) ans|=(1<<i);
	}
	printf("%d\n",ans);
	return 0;
}

标签:cnt,include,logs,int,1322B,CodeForces,位为,Present,2k
来源: https://www.cnblogs.com/newblg/p/14865279.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有