L i n k Link Link
D e s c r i p t i o n Description Description
Mr.S是个神仙,一天他在研究数论时,书上有这么一个问题:求不超过n两两的数的gcd。
SarvaTathagata这么神仙的人当然觉得这个是sb题啦。学习之余,他还发现gcd的某一个特别好的性质:如果有两个数i,j满足gcd(i,j)=i ^ j(这里的^为c++中的异或)的话,那么这两个数组成的数对(i,j)就是一个nb的数对(这里认为(i,j)和(j,i)为相同的,并不需要计算2次)。
当然,SarvaTathagata并不会只满足于判断一个数对是否nb,他还想知道满足两个数都是不超过n并且nb的数对有多少个。
由于SarvaTathagata实在是太神仙了,他认为这种题实在是太简单了。于是他找到了你,看看你是否能解决这个问题。
S a m p l e Sample Sample I n p u t Input Input
样例输入1
12
样例输入2
123456
S a m p l e Sample Sample O u t p u t Output Output
样例输出1
8
样例输出2
214394
T r a i n Train Train o f of of T h o u g h t Thought Thought
∵
g
c
d
(
a
,
b
)
<
=
a
−
b
gcd(a, b)\ <=\ a - b
gcd(a,b) <= a−b,
a
x
o
r
b
>
=
a
−
b
a\ xor\ b >= a-b
a xor b>=a−b
∴
g
c
d
(
a
,
b
)
=
a
x
o
r
b
=
a
−
b
gcd(a, b) = a\ xor\ b = a \ - \ b
gcd(a,b)=a xor b=a − b
然后枚举这个差,然后再枚举倍数就好了
C o d e Code Code
#include<iostream>
#include<cstdio>
using namespace std;
int n, ans;
int main()
{
scanf("%d", &n);
for (int c = 1; c <= n; ++c)
for (int a = 2 * c; a <= n; a += c)
if (c == (a ^ (a - c))) ans++;
printf("%d", ans);
}