GCD XOR
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4454
题目大意:求gcd(a, b) = a ^ b且满足1 <= b <= a <= N的(a, b)对数,其中N小于等于3e7
样例:
SampleInput
2
7
20000000
SampleOutput
Case 1: 4
Case 2: 34866117
题目分析:首先若a == b则显然gcd(a, b) != a ^ b,在b < a时考虑两个不等式:
1. gcd(a, b) <= a - b,这个不用解释了
2. a ^ b >= a - b,设a >= b把a,b化成二进制,假设ai位为0,对应的bi位为1,则交换它们,异或值不会变化,但是a - b变大了,因此把所有对应位置中ai与bi不同的位置处令ai为1,bi为0,则得到a ^ b == a - b,其余的a ^ b显然都是大于a - b的,因此结论成立
又因为a ^ b = c => a ^ c = b,这个好证:a ^ b = c => a ^ a ^ b = a ^ c => b = a ^ c
由以上推论可得若gcd(a, b) = a ^ b则a ^ b = a - b 且 gcd(a, b) = a - b,因此a - b是a的约数,因此可以枚举a-b的值,用筛子得到a,再判断是否有a ^ b = a - b即可,预处理前n个数的(a, b)对数,O(1)查询
#include <cstdio>
int const MAX = 30000005;
int ans[MAX];
void pre()
{
for(int i = 1; i < MAX; i++) // i 即 a - b
{
for(int j = i + i; j < MAX; j += i) // j 即 a
if((j ^ (j - i)) == i) // 判断是否有 a ^ b == a - b
ans[j] ++;
ans[i] += ans[i - 1];
}
}
int main()
{
pre();
int T;
scanf("%d", &T);
for(int ca = 1; ca <= T; ca++)
{
int n;
scanf("%d", &n);
printf("Case %d: %d\n", ca, ans[n]);
}
}