B. Rock and Lever(思维+位运算+贪心)

https://codeforces.com/contest/1420/problem/B


思路:位运算嘛..刚前天做了一道类似的题。考虑最高位的贪心.为什么呢?

把数字按照二进制位去思考。

 ai & aj≥ai⊕aj

比如

1 1 0

0  0 1

把这两个数进行题目的操作发现,&的操作会让最高位变成0,而异或会变成1,使得不满足题目的统计条件。

再比如

1 __   __

1 __  ___ 

每个位置1和0两个情况枚举每个情况会发现只有这种情况能满足条件。所以也就说找最高位同为1的数的对数。用一个siz[i]统计最高位都为1的个数,里面每一对都能满足,一个块里的个数和siz[i]的个数有关。

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=1e5+100;
typedef long long LL;
LL a[maxn],d[40];
bool vis[maxn];
int main(void)
{
  cin.tie(0);std::ios::sync_with_stdio(false);
  LL t;cin>>t;
  while(t--)
  {
  	 LL n;cin>>n;
  	 for(LL i=1;i<=n;i++) cin>>a[i],vis[i]=0;
  	 for(LL i=0;i<=40;i++) d[i]=0;
  	 for(LL i=32;i>=1;i--)
  	 {
  	 	for(LL j=1;j<=n;j++)
		{
			if(a[j]&(1<<(i-1))&&!vis[j]) vis[j]=1,d[i]++;	
		}	
	 }
	 LL sum=0;
	 for(LL i=1;i<=32;i++) if(d[i]) sum+=(d[i]*(d[i]-1))/2;
	 cout<<sum<<endl;
  }
return 0;
}

猜你喜欢

转载自blog.csdn.net/zstuyyyyccccbbbb/article/details/108805684