背景:
一年之前看到的题了。
题目传送门:
https://www.luogu.org/problem/UVA12716
题意:
求
1
≤
b
≤
a
≤
n
1≤b≤a≤n
1≤b≤a≤n的数对满足
gcd
(
a
,
b
)
=
a
xor
b
\gcd(a,b)=a \text{ xor } b
gcd(a,b)=a xor b的组数。
思路:
设
gcd
(
a
,
b
)
=
a
xor
b
=
c
\gcd(a,b)=a \text{ xor } b=c
gcd(a,b)=a xor b=c
考虑两个不等式:
[
1
]
[1]
[1]:
考虑更相减损术,有:
gcd
(
a
,
b
)
=
gcd
(
b
,
a
−
b
)
=
c
\gcd(a,b)=\gcd(b,a-b)=c
gcd(a,b)=gcd(b,a−b)=c
因此显然有
a
−
b
≥
c
a-b≥c
a−b≥c。
[
2
]
[2]
[2]:
结论:
a
−
b
≤
c
a-b≤c
a−b≤c。
将
a
,
b
a,b
a,b转成二进制,考虑当前这一位
i
i
i,由于
a
≥
b
a≥b
a≥b,因此若
a
i
=
1
a_i=1
ai=1,则
b
i
=
0
,
1
b_i=0,1
bi=0,1显然成立;若
a
i
=
0
,
b
i
=
0
a_i=0,b_i=0
ai=0,bi=0,显然成立;若
a
i
=
0
,
b
i
=
1
a_i=0,b_i=1
ai=0,bi=1,则前面一定存在一个
j
<
i
j<i
j<i,且
a
j
=
1
,
b
j
=
0
a_j=1,b_j=0
aj=1,bj=0,则这一段的异或结果一定形如
100..001
100..001
100..001,而这一段的减法结果一定形如
01...11
01...11
01...11,成立。
综上
a
−
b
=
c
a-b=c
a−b=c。
因此
gcd
(
a
,
b
)
=
a
xor
b
=
a
−
b
\gcd(a,b)=a \text{ xor } b=a-b
gcd(a,b)=a xor b=a−b时成立。
考虑枚举
gcd
(
a
,
b
)
\gcd(a,b)
gcd(a,b)作为
b
b
b,枚举
gcd
(
a
,
b
)
\gcd(a,b)
gcd(a,b)的倍数作为
a
a
a,此时已经满足了
gcd
\text{gcd}
gcd的限制,直接判断
a
xor
b
,
a
−
b
a \text{ xor } b,a-b
a xor b,a−b是否相等即可。
可以类似埃氏筛来做。
离线,前缀和一下即可。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
int f[30000010];
void init(int ma)
{
for(int i=1;i<=ma;i++)
for(int j=(i<<1);j<=ma;j+=i)
if(j-i==(i^j)) f[j]++;
for(int i=1;i<=ma;i++)
f[i]+=f[i-1];
}
int main()
{
int T;
init(30000000);
scanf("%d",&T);
for(int i=1;i<=T;i++)
{
scanf("%d",&n);
printf("Case %d: %d\n",i,f[n]);
}
}