原题链接
题目大意
定义
A
n
d
And
And 为按位与操作,
X
o
r
Xor
Xor 为按位异或操作。
给一个包含
n
n
n 个元素的正整数序列
a
a
a,计算满足
a
i
A
n
d
a
j
≥
a
i
X
o
r
a
j
a_i\ And\ a_j≥a_i\ Xor \ a_j
ai And aj≥ai Xor aj 的
(
i
,
j
)
(i,j)
(i,j)
(
i
<
j
)
\ \ \ (i<j)
(i<j) 的数对数量。
解题思路
对于本蒟蒻来讲,这题还挺数学。
先了解一下
A
n
d
And
And 的性质:
a
A
n
d
b
≤
m
i
n
(
a
,
b
)
a\ And\ b\le min(a,b)
a And b≤min(a,b) ,请记住,这很重要。
现在再来看
X
o
r
Xor
Xor 的性质,由于位运算不够位数回自动补0,当出现两数
a
,
b
a,b
a,b 时:
若
⌊
log
2
a
⌋
≠
⌊
log
2
b
⌋
\left \lfloor \log_2a \right \rfloor \ne \left \lfloor \log_2b \right \rfloor
⌊log2a⌋=⌊log2b⌋(两数的二进制长度不相等),
则
⌊
log
2
(
a
X
o
r
b
)
⌋
=
max
(
⌊
log
2
a
⌋
,
⌊
log
2
b
⌋
)
\left \lfloor \log_2(a\ Xor\ b) \right \rfloor =\max(\left \lfloor \log_2a \right \rfloor ,\left \lfloor \log_2b \right \rfloor)
⌊log2(a Xor b)⌋=max(⌊log2a⌋,⌊log2b⌋)(因为较短的数会自动补0)
若
⌊
log
2
a
⌋
=
⌊
log
2
b
⌋
\left \lfloor \log_2a \right \rfloor=\left \lfloor \log_2b \right \rfloor
⌊log2a⌋=⌊log2b⌋(两数的二进制长度不相等),
则
⌊
log
2
(
a
X
o
r
b
)
⌋
<
log
2
a
,
⌊
log
2
(
a
X
o
r
b
)
⌋
<
log
2
b
\left \lfloor \log_2(a\ Xor\ b) \right \rfloor <\log_2a,\left \lfloor \log_2(a\ Xor\ b) \right \rfloor <\log_2b
⌊log2(a Xor b)⌋<log2a,⌊log2(a Xor b)⌋<log2b(因为第一位会变成0)
也就是说:
a
X
o
r
b
<
min
(
a
,
b
)
a\ Xor\ b< \min(a,b)
a Xor b<min(a,b)
联系上文
a
A
n
d
b
≤
m
i
n
(
a
,
b
)
a\ And\ b\le min(a,b)
a And b≤min(a,b) 我们可以发现,只有当
⌊
log
2
a
⌋
=
⌊
log
2
b
⌋
\left \lfloor \log_2a \right \rfloor=\left \lfloor \log_2b \right \rfloor
⌊log2a⌋=⌊log2b⌋ 时,
a
A
n
d
b
≤
a
X
o
r
b
a\ And\ b\le a\ Xor\ b
a And b≤a Xor b 才有可能实现。于是,我们可以将数列中的数按照二进制长度分类,再在每一类别中进行枚举,答案便出来了!
(非正解,若
a
a
a 中所有的数以二为底的对数都一样,会被卡掉!)
代码实现
#include<bits/stdc++.h>
using namespace std;
int t,f[10010],a[10010],Log2_of_a[10010],n;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>t;
for(int i=1;i<=t;i++){
cin>>n;
int Max_a=0;
vector<int> Log_2[10010];
for(int j=1;j<=n;j++){
cin>>a[j];
Max_a=max(Max_a,a[j]);
Log2_of_a[j]=floor(log2(a[j]));
Log_2[Log2_of_a[j]].push_back(j);
}
int ans=0;
for(int j=1;j<=n;j++){
int log2a=Log2_of_a[j];
for(int k=0;k<Log_2[log2a].size();k++){
if(Log_2[log2a][k]!=j&&j<Log_2[log2a][k]){
if((a[j]&a[Log_2[log2a][k]])>=(a[j]^a[Log_2[log2a][k]]))
ans++;
}
}
}
cout<<ans<<endl;
}
return 0;
}