zoj 3870 Team Formation (数位统计问题)

来源:互联网 发布:night changes知乎 编辑:程序博客网 时间:2024/05/24 04:17

题意:

给出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;}


0 0
原创粉丝点击