题意:
给出n个数组成的序列,求满足这样的数对的个数,i!=j,a[i]^a[j]>max(a[i],a[j]);
题解:
这题可以从二进制的角度去观察,我们可以枚举数对中的某个数i,然后计算有多少个j满足。对于j个数的计算,通过2进制数位的分析会发现,只要小于a[i]并且最高为和a[i]的对应位是不同的数就满足条件。预处理出最高位数是1的个数,剩下就是暴力枚举i和a[i]的位。
#include<iostream> #include<math.h> #include<stdio.h> #include<algorithm> #include<string.h> #include<vector> #include<queue> #include<map> #include<set> #define B(x) (1<<(x)) using namespace std; typedef long long ll; void cmax(int& a,int b){ if(b>a)a=b; } void cmin(int& a,int b){ if(b<a)a=b; } void cmax(ll& a,ll b){ if(b>a)a=b; } void cmin(ll& a,ll b){ if(b<a)a=b; } void add(int& a,int b,int mod){ a=(a+b)%mod; } void add(ll& a,ll b,ll mod){ a=(a+b)%mod; } const int oo=0x3f3f3f3f; const ll OO=0x3f3f3f3f3f3f3f3f; const ll MOD=1000000007; const int maxn = 100000 ; int num[40],a[maxn],bit[40]; int get_bit(int n){ int dig=0; while(n){ n/=2; dig++; } return dig; } void Count(int n){ int bit=get_bit(n); num[bit]++; } int get_bin(int n){ int len=0; while(n){ bit[++len]=n%2; n/=2; } return len; } int main(){ //freopen("E:\\read.txt","r",stdin); int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); memset(num,0,sizeof num); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); Count(a[i]); } ll ans=0; for(int i=1;i<=n;i++){ int len=get_bin(a[i]); for(int j=len;j>=1;j--) if(!(bit[j]&1))ans+=num[j]; } cout<<ans<<endl; } return 0; }