Codeforces769D-k-Interesting Pairs Of Integers-位运算

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

题意:传送门

 原题目描述再最下面。

 给你n(1e5)个数,每个数范围1e4。问有多少对数的异或和位k。

思路:

 考虑暴力枚举,但是不是直接枚举n。而是离散化之后枚举n,统计异或和二进制中1的数量。记得预先记录下每个数出现的次数。

 对于统计二进制位中1的个数有很多方法。

AC代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <bitset>
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long LL;
const int N = 1e6 + 7;
const int INF = 0x3f3f3f3f;
int n, k;
int ar[N], br[N], now[N];
LL num[N];
void init(){
  memset(num,0,sizeof(num));}

int main(int argc, char const *argv[]){
  while(~scanf("%d%d", &n, &k)){
    init();
    for(int i = 0; i < n; ++i){
      scanf("%d", &ar[i]);
      br[i] = ar[i];
      num[ar[i]]++;
    }
    sort(br, br+n);
    int p = 0;
    for(int i = 1; i < n; ++i){
      if(br[i]!=br[i-1]){
        br[++p] = br[i];
      }
    }
    for(int i = 0; i < n; ++i){
      now[i] = lower_bound(br, br+p+1, ar[i]) - br;
    }
    LL ans = 0;
    for(int i = 0; i <= p; ++i){
      for(int j = i; j <= p; ++j){
        bitset<32> a(br[i]^br[j]);
        if(a.count()==k){
          if(i==j){
            ans += num[br[i]]*(num[br[j]]-1)/2;
          }else{
            ans += num[br[i]]*num[br[j]];            
          }
        }
      }
    }
    printf("%lld\n", ans);
  }
  return 0;
}


统计二进制中1的数量:

//方法一:
int bitCount(unsigned int n){
    unsigned int tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111);
    return ((tmp + (tmp >> 3)) & 030707070707) % 63;
}

//方法二:
bitset<32> a(n);
a.count();

//方法三:
__builtin_popcount(n)//返回二进制位中有多少个1
__builtin_parity(n)//返回二进制位中1的数量的奇偶性,奇数返回1,偶数返回0
__builtin_ffs(n)//返回二进制末尾最后一个1的位置,从一开始
__builtin_ctz(n)//返回二进制末尾后面0的个数,当n为0时,和n的类型有关


原题目描述:

这里写图片描述

猜你喜欢

转载自blog.csdn.net/qq_39599067/article/details/81128941
今日推荐