【模拟题】异或 (二进制)

异或

问题描述

给定序列\(𝐴\),计算\(\sum^{n}_{i=1}\sum^{n}_{j-i}A_i and A_{i+1} and .... and A_j\)

输入格式】

第一行一个整数\(𝑁\).
第二行\(𝑁\)个整数描述\(𝐴\).

输出格式

一行输出答案\(ans\).

样例输入

3
1 2 3

样例输出

8

数据规模

对于\(10\%\)的数据,\(𝑁 ≤ 100, 𝐴_i ≤ 1\).
对于\(20\%\)的数据,\(𝑁 ≤ 100\).
对于\(30\%\)的数据,\(𝑁 ≤ 1000\)
对于\(40\%\)的数据,\(𝑁 ≤ 100000\)
以上的数据档互不相交.
对于所有的数据,满足\(1 ≤ 𝑁 ≤ 10^5, 0 ≤ 𝐴_i ≤ 2^{31 − 1}\).

题解

我们可以去利用二进制的\(\&\)的性质,去计算二进制每一位的\(1\)的贡献。

因为\(\&\)后有一位变成\(0\),那么它永远不会有贡献了(永远不会变成\(1\)),然后去计算会有多少个数会有这个\(1\)(权值为\(1<<i\))的贡献。

注意,一定要用\(1LL\),否则\(2^{32}\)会炸。

code(&):

#include<iostream>
#include<cstdio>
#include<cctype>
#define N 100005
#define ll long long 
#define R register
using namespace std;
template<typename T>inline void read(T &a){
	char c=getchar();T x=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	a=f*x;
}
int n,a[N],cnt;
ll ans;
int main(){
	read(n);
	for(R int i=1;i<=n;i++)read(a[i]);
	for(R ll i=0;i<=32;i++){
		cnt=0;
		for(R int j=1;j<=n;j++){
			if(a[j]&(1LL<<i))cnt++;
			else cnt=0;
			ans+=cnt*(1LL<<i);
		}
	}
	printf("%lld\n",ans);
	return 0;
}

拓展

后来大佬GMPotlc又告诉了我一个处理异或(^)的做法。

都是利用二进制中的性质,异或偶数次无贡献,异或奇数次才有贡献。

而且若现在\(1\)的个数为奇数,那么就会与前面偶数次的产生贡献;当前为偶数,则反之。

所以我们记录一个出现\(1\)奇数次的个数\(a\)和偶数次的个数\(b\),总个数\(cnt\)

\(cnt\)为奇数 \(ans+=(b*(1LL<<i)),a++;\)

\(cnt\)为偶数 \(ans+=(a*(1LL<<i)),b++;\)

注意:初始化 ,\(b=1\)(因为一开始\(0\)\(1\)也是偶数)。

code(^):

#include<iostream>
#include<cstdio>
#include<cctype>
#define N 100005
#define ll long long 
#define R register
using namespace std;
template<typename T>inline void read(T &a){
	char c=getchar();T x=0,f=1;
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	a=f*x;
}
int n,init[N],cnt,a,b;
ll ans;
int main(){
	read(n);
	for(R int i=1;i<=n;i++)read(init[i]);
	for(R ll i=0;i<=32;i++){
		cnt=0;a=0;b=1;
		for(R int j=1;j<=n;j++){
			if(init[j]&(1LL<<i))cnt++;
			if(cnt&1)ans+=(1LL<<i)*b,a++;
			else ans+=(1LL<<i)*a,b++;
		}
	} 
	printf("%lld\n",ans);
	return 0;
}
posted @ 2018-10-26 21:29  ZAGER  阅读(472)  评论(0编辑  收藏  举报