题目描述
若两个数x,y,他们在二进制形式下有k位是不同的,我们称这两个数字是k耦合的。
例如二进制1001和0110是满足4耦合的,他们有4位不同
现在给出一个非负整数序列a1,a2,.....,an,你需要求存在多少对(i,j),i<j使得ai,aj是满足k耦合的。
输入格式
第一行输入n,k,表示序列长度和耦合要求
第二行输入n个数,表示序列a
输出格式
输出一个数字表示答案
样例 #1
样例输入 #1
text
样例输出 #1
text
样例 #2
样例输入 #2
text1 2
| 6 0 200 100 100 100 200 200
|
样例输出 #2
text
提示
数据范围:
(2 ≤ n ≤ 105,0 ≤ k ≤ 14)
(0 ≤ ai ≤ 104)
题解
首先最先想到的是枚举i,j判断ai,aj是否为k耦合。时间复杂度尾或者O(n2)。得到的结果是超超时。考虑优化,我们发现题目所给的值域只有104,也就是说会出现重复的数字,我们对0到10000依次枚举计算是不会超时的,所以我们需要统计重复的数字来避免重复计算,减少时间。
首先我们可以创建一大小为略大于104数组,下表表示这个数,对应的值表示出现的次数。
然后我们依次枚举计算是否符合条件即可。
k耦合的判断方法为ai^aj,因为考虑异或二进制位上相同则为0,考虑两数字异或后有二进制上有几个1即可。计算一个数的二进制上有几个一有2种办法:
法一:mod2法
1 2 3 4 5 6 7 8 9 10 11 12
| int a; int cnt=0; cin>>a; while (a!=0) { if (a%2==1) { cnt++; } a/=2; } cout<<cnt<<endl;
|
法二:位运算法
1 2 3 4 5 6 7 8 9
| int b; int cnt=0; cin>>b; while (b!=0) { cnt+=b&1; b>>=1; } cout<<cnt<<endl;
|
下面是完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| #include<bits/stdc++.h> using namespace std; bool check(int a,int k) { int b=a; int cnt=0; while (b!=0) { cnt+=b&1; b>>=1; } return cnt==k; } int main() { int n,k; long long sum=0; cin>>n>>k; int temp; int mp[10004]={0}; for (int i=1;i<=n;i++) { cin>>temp; mp[temp]++; } if (k==0) { for (int i=0;i<=10000;i++) { if (mp[i]>0) { sum+=mp[i]*(mp[i]-1); } } sum/=2; } else { for (int i=0;i<10000;i++) { if (mp[i]>0) { for (int j=i+1;j<=10000;j++) { if (mp[j]>0) { if (check(i^j,k)) { sum+=mp[i]*mp[j]; } } } } } } cout<<sum<<endl; return 0; }
|