题意:给定一个长度为n的a数组,(2=<n<=1e5,0=<ai<=1e4),和一个数字k,程序要求输出满足下标对(I<j),ai与aj(二进制)有k位不同,的对数
思路:预处理用一个数组记录数字I有几位为1,ai与aj有几位不同可以通过num[I^j]确定,1e4的二进制有14位,则I^j的做为14位1,num至少得开16383+1.
#include<cstdio>
#include<cstring>
using namespace std;
int num[16384];
long long vis[10001];
void init()
{
memset(num,0,sizeof(num));
for(int i=1;i<16384;i++)
{
int cc=i;
while(cc)
{
num[i]+= (cc%2);
cc/=2;
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
int n,k,a;
init();
while(scanf("%d%d",&n,&k)!=EOF)
{
long long ans=0;
memset(vis,0,sizeof(vis));
for(int i=0;i<n;i++)
{
scanf("%d",&a);
vis[a]++;
}
for(int i=0;i<10001;i++)
{
if(vis[i]==0)continue;
for(int j=i;j<10001;j++)
{
if(vis[j]>0&&num[i^j]==k)//如果i和j存在于a数组
{
//如果i==j,则任意两个可以“匹配” c(2,n)
if(i==j)ans+= ((vis[i])*(vis[i]-1))/2;
//i!=j 则i只能与j“配对”数量也即vis[i]*vis[j]
else ans+=(vis[i]*vis[j]);
}
}
}
printf("%I64d\n",ans);
}
}