异或
题目大意
问你不小于 n n n的数对 ( a , b ) (a,b) (a,b),有多少个满足 g c d ( a , b ) = a ⊕ b gcd(a,b)=a \oplus b gcd(a,b)=a⊕b
输入样例#1
12
输出样例#1
8
输入样例#2
123456
输出样例#2
214394
数据范围
测试点 | 数据规模 |
---|---|
1 | 10 |
2 | 100 |
3 | 1000 |
4 | 5000 |
5 | 10000 |
6 | 100000 |
7 | 500000 |
8 | 1000000 |
9 | 5000000 |
10 | 20000000 |
解题思路
我们设
c
=
g
c
d
(
a
,
b
)
c=gcd(a,b)
c=gcd(a,b)
我们可以枚举
c
c
c
然后枚举
a
a
a是
c
c
c的多少倍
由此得出
a
,
c
a,c
a,c
我们可以通过
g
c
d
gcd
gcd求出
b
b
b然后判断是否满足
a
⊕
b
=
c
a \oplus b=c
a⊕b=c
但是这个时间复杂度过大,我们要进行优化
我们先证明
a
−
b
⩽
a
⊕
b
a-b \leqslant a \oplus b
a−b⩽a⊕b
我们观察以下两个字符串
(
x
>
y
)
(x>y)
(x>y)
x
:
x:
x: 11001
y
:
y:
y: 00101
x
o
r
:
xor:
xor: 11100
1
.
.
.对于
x
,
y
x,y
x,y都是1的位
x
o
r
xor
xor和
−
-
−得出结果都是0
2
.
.
.对于只有
y
y
y是1的位
因为
a
>
b
a>b
a>b,所以在更高的位肯定有只有
x
x
x是1的位,这样减出来的结果才可能是正数
因此
−
-
−得出的结果是更高一位只有
x
x
x是1的位减这一位
而
x
o
r
xor
xor得出的是这两位的和
3
.
.
.对于只有
x
x
x是1且无需用去减的位
x
o
r
xor
xor和
−
-
−得出结果都是1
综上所述,
a
−
b
⩽
a
⊕
b
a-b \leqslant a \oplus b
a−b⩽a⊕b
现在我们来证明
c
⩽
a
−
b
c \leqslant a-b
c⩽a−b
因为
c
=
g
c
d
(
a
,
b
)
c=gcd(a,b)
c=gcd(a,b)
我们设
a
=
c
∗
a
s
a=c*as
a=c∗as
b
=
c
∗
b
s
b=c*bs
b=c∗bs
若
a
=
b
a=b
a=b则
g
c
d
(
a
,
b
)
=
1
gcd(a,b)=1
gcd(a,b)=1
a
⊕
b
=
0
a \oplus b=0
a⊕b=0
g
c
d
(
a
,
b
)
≠
a
⊕
b
gcd(a,b) \neq a \oplus b
gcd(a,b)=a⊕b
∴
a
≠
b
\therefore a \neq b
∴a=b
∵
a
≠
b
且
a
⩾
b
\because a \neq b 且a \geqslant b
∵a=b且a⩾b
a
>
b
a > b
a>b
∵
a
s
>
b
s
\because as > bs
∵as>bs
a
s
−
b
s
⩾
1
as - bs\geqslant 1
as−bs⩾1
(
a
s
−
b
s
)
×
c
⩾
c
(as - bs)\times c \geqslant c
(as−bs)×c⩾c
a
−
b
⩾
c
a-b\geqslant c
a−b⩾c
若
a
−
b
≠
c
a-b\neq c
a−b=c
则
c
<
a
−
b
⩽
a
⊕
b
c < a-b \leqslant a \oplus b
c<a−b⩽a⊕b
c
<
a
⊕
b
c<a \oplus b
c<a⊕b
无法满足
c
=
a
⊕
b
c=a \oplus b
c=a⊕b
∴
a
−
b
=
c
\therefore a-b=c
∴a−b=c
这样我们通过
b
=
a
−
c
b=a-c
b=a−c求出
b
b
b
然后判断
c
c
c是否等于
a
⊕
b
a \oplus b
a⊕b即可
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
int n, a, b, ans;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n / 2; ++i)
for (int j = 2; i * j <= n; ++j)
{
a = i * j;
b = a - i;//求b
if (i == (a^b)) ans++;
}
printf("%d", ans);
return 0;
}