UVA 12716 GCD XOR (數論 gcd和異或不等式)

_TCgogogo_發表於2015-09-08

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]);
	}
}