模拟题异或 (二进制)
Posted zager
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟题异或 (二进制)相关的知识,希望对你有一定的参考价值。
异或
问题描述
给定序列(??),计算(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
",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
",ans);
return 0;
}
以上是关于模拟题异或 (二进制)的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode810. 黑板异或游戏/455. 分发饼干/剑指Offer 53 - I. 在排序数组中查找数字 I/53 - II. 0~n-1中缺失的数字/54. 二叉搜索树的第k大节点(代码片段