CF1332B present(位运算/思维)

传送门

题意:给定一个数组a,求

(a1+a2)⊕(a1+a3)⊕…⊕(a1+an)⊕

(a2+a3)⊕…⊕(a2+an)

…⊕(an−1+an)

n<=4e5

思考:显然是思考位运算,一位一位去考虑。我们可以发现,第i位只有拥有奇数个数的1时才可以产生贡献。那么我们就考虑产生1的情况。

1)第i-1位没有进位时,若第i位为1,则统计其他数字第i位为0的情况

2)第i-1位没有进位时,若第i位为0,则统计其他数字第i位为1的情况

3)第i-1位进位时,若第i位为1,则统计其他数字第i位为1的情况

4)第i-1位进位时,若第i位为0,则统计其他数字第i位为0的情况

同时考虑不能重复,所以枚举时要稍加注意。

考虑每一位,每一位去排序一遍,则复杂度为O(30*n*logn)

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define pll pair<long long,long long>
#define pb push_back
#define sz size
#define IOS ios::sync_with_stdio(0), cin.tie(0),cout.tie(0)
#define endl "\n"
const ll inf=1ll<<60;
const int mod=998244353;
mt19937 rnd(std::chrono::system_clock::now().time_since_epoch().count());
//uniform_int_distribution<long long> dist(0, 100000);//随机数限定范围:dist(rnd);
const int N=400010;
int n,a[N],suf1[N],suf0[N],g[N];
array<int,2> b[N];
inline int high(int x,int y){
	return ((x>>y)&1);
}
void solve(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	int ans=0;
	for(int bit=1;bit<=30;bit++){
		int mask=1<<(bit-1);
		for(int i=1;i<=n;i++){
			b[i]={(a[i]&(mask-1)),((a[i]>>(bit-1))&1)};
		}
		sort(b+1,b+n+1);
		suf1[0]=suf0[0]=0;
		for(int i=1;i<=n;i++){
			if(b[i][1])
				suf1[i]=suf1[i-1]+1,suf0[i]=suf0[i-1];
			else
				suf0[i]=suf0[i-1]+1,suf1[i]=suf1[i-1];
		}
		for(int i=1;i<=n;i++) g[i]=b[i][0];
//		for(int i=1;i<=n;i++) cout<<suf0[i]<<" "<<suf1[i]<<"  |--->"<<i<<"<---\n";
		int cnt=0;
		for(int i=1;i<n;i++){
			int tmp=lower_bound(g+i+1,g+n+1,mask-g[i])-g;
			//不进位
			if(b[i][1])cnt+=suf0[tmp-1]-suf0[i];
			else cnt+=suf1[tmp-1]-suf1[i];
			//进位
			if(b[i][1]) cnt+=suf1[n]-suf1[tmp-1];
			else cnt+=suf0[n]-suf0[tmp-1];
		}
		if(cnt%2) ans+=(1<<(bit-1));//cout<<cnt<<"\n";
	}
	cout<<ans<<"\n";
}
signed main(){
//	IOS;
	int _test=1,_tot=0;
//	cin>>_test;
	while(_test--){
//		printf("Case #%d: \n",++_tot);
		solve();
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值