异或
题目大意
问你不小于nnn的数对(a,b)(a,b)(a,b),有多少个满足gcd(a,b)=a⊕bgcd(a,b)=a \oplus bgcd(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=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
我们可以枚举ccc
然后枚举aaa是ccc的多少倍
由此得出a,ca,ca,c
我们可以通过gcdgcdgcd求出bbb然后判断是否满足a⊕b=ca \oplus b=ca⊕b=c
但是这个时间复杂度过大,我们要进行优化
我们先证明a−b⩽a⊕ba-b \leqslant a \oplus ba−b⩽a⊕b
我们观察以下两个字符串(x>y)(x>y)(x>y)
x:x:x: 11001
y:y:y: 00101
xor:xor:xor: 11100
1...对于x,yx,yx,y都是1的位xorxorxor和−-−得出结果都是0
2...对于只有yyy是1的位
因为a>ba>ba>b,所以在更高的位肯定有只有xxx是1的位,这样减出来的结果才可能是正数
因此−-−得出的结果是更高一位只有xxx是1的位减这一位
而xorxorxor得出的是这两位的和
3...对于只有xxx是1且无需用去减的位xorxorxor和−-−得出结果都是1
综上所述,a−b⩽a⊕ba-b \leqslant a \oplus ba−b⩽a⊕b
现在我们来证明c⩽a−bc \leqslant a-bc⩽a−b
因为c=gcd(a,b)c=gcd(a,b)c=gcd(a,b)
我们设
a=c∗asa=c*asa=c∗as
b=c∗bsb=c*bsb=c∗bs
若a=ba=ba=b则
gcd(a,b)=1gcd(a,b)=1gcd(a,b)=1
a⊕b=0a \oplus b=0a⊕b=0
gcd(a,b)≠a⊕bgcd(a,b) \neq a \oplus bgcd(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>ba > ba>b
∵as>bs\because as > bs∵as>bs
as−bs⩾1as - bs\geqslant 1as−bs⩾1
(as−bs)×c⩾c(as - bs)\times c \geqslant c(as−bs)×c⩾c
a−b⩾ca-b\geqslant ca−b⩾c
若a−b≠ca-b\neq ca−b=c
则c<a−b⩽a⊕bc < a-b \leqslant a \oplus bc<a−b⩽a⊕b
c<a⊕bc<a \oplus bc<a⊕b
无法满足c=a⊕bc=a \oplus bc=a⊕b
∴a−b=c\therefore a-b=c∴a−b=c
这样我们通过b=a−cb=a-cb=a−c求出bbb
然后判断ccc是否等于a⊕ba \oplus ba⊕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;//求bif (i == (a^b)) ans++;}printf("%d", ans);return 0;
}