第二集,未来的我发量这么捉急的吗

题意:

有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+;

int a[maxn];

int main(){

    ios::sync_with_stdio(false);

    cin.tie();

    int T;

    cin>>T;

    while(T--){

        map<int,int> mp;

        int n,k;

        cin>>n>>k;

        ll ans=;

        for(int i=;i<=n;i++){

            cin>>a[i];

            ans+=mp[k-a[i]];

            mp[a[i]]++;

        }

        cout<<ans<<endl;

    }

    return ;

}
05-01 02:05