思路
很明显如果两个数a,b为一组那么a^b= 2 31 2^{31} 231-1,所以我们只要枚举 a i a_i ai^ 2 31 2^{31} 231-1得到x,在从数组中找是否有一个数 a j a_j aj等于x就可以说明 a i a_i ai和 b j b_j bj是一组。
由于 b j b_j bj不能重复使用只要标记一下就好了。注意由于 a i a_i ai会找一次, b j b_j bj会找一次,所以要将找到的数量除2。找 b j b_j bj过程很显然不能枚举,顺其自然的就想到二分了。
时间复杂度O(nlogn)。
代码
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
#define Pqueue priority_queue
#define FAST ios::sync_with_stdio(false),cin.tie(0);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=1e6+5;
const ll num=2147483647;
const ll INF=0x3f3f3f3f;
ll a[N];
bool vis[N];
int main()
{
FAST
ll t,n,i,cnt;
cin>>t;
while (t--)
{
cnt=0;
memset(vis,0,sizeof(vis));
cin>>n;
for (i=1;i<=n;i++) cin>>a[i];
sort(a+1,a+n+1);
for (i=1;i<=n;i++)
{
ll x=a[i]^num;
ll p=lower_bound(a+1,a+n+1,x)-a;
if (a[p]==x&&!vis[p])
cnt++,vis[p]=1;
else if (a[p]==x&&vis[p])
{
ll k=p+1;
for (int j=k;j<=n;j++)
{
if (a[j]!=a[p])
break;
if (a[j]==a[p]&&!vis[j])
{
cnt++;
vis[j]=1;
break;
}
}
}
}
cout<<n-cnt/2<<endl;
}
return 0;
}