福建工程学院第十四届ACM校赛B题题解
第二集,未来的我发量这么捉急的吗
题意:
有n个数,请问有多少对数字(i,j)(1<=i<j<=n),满足(a[i]^a[j])+((a[i]&a[j])<<1)=k
思路:
仔细观察不难发现这个位运算有点不一般,其实(a[i]^a[j])+((a[i]&a[j])<<1)这个是等价于a[i]+a[j]的,具体的原理是这样的,我们模拟一下二进制下的加法,如果这一位都是0,加完之后还是0,如果这一位是一个0和一个1,加完之后变成了1,如果这一位都是1,加完之后又就变成了0,然后向前进位,可以观察到在不考虑进位的情况下,二进制加法和异或的性质是一样的,0+0=0,0+1=1+0=1,1+1=0,然后我们发现a[i]&a[j]其实是把二进制都为1的位置提取了出来,因为两个数都为1的情况是需要进位的,所以这里模拟二进制加法,多了个(a[i]&a[j])<<1这样的进位量。
代码实现
这题代码挺简单,排序双指针或者标记都行,map标记代码如下:
#include <iostream> #include <cstring> #include <map> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 1e5+7; int a[maxn]; int main(){ ios::sync_with_stdio(false); cin.tie(0); int T; cin>>T; while(T–){ map<int,int> mp; int n,k; cin>>n>>k; ll ans=0; for(int i=1;i<=n;i++){ cin>>a[i]; ans+=mp[k-a[i]]; mp[a[i]]++; } cout<<ans<<endl; } return 0; }
|