uva12716: GCD XOR(埃筛)

题目大意:输入一个整数n (1 <= n <= 30000000),有多少对整数(a,b)满足 1 <= b <= a <= n,切gcd(a,b) = a xor b。例如 n = 7时,有4对:(3,2),(5,4),(6,4),(7,6)。

解法:要得到答案肯定是要枚举的,但枚举a,b肯定会超时,设 c = a xor b,则 b = a xor c,于是变成枚举a,c,枚举a,c为什么会更快呢?因为c是a的约数,可以像筛法那样枚举,复杂度nlogn,并且在o(1)时间内求出b,只要在logn时间内判断一下gcd(a,b) = c 就行了,总复杂度为nlog^n,还是会超时。
打个表,打出前1000项,观察,发现满足条件的式子,都有a - b = c,移项得:b = a - c。枚举c 和 a时,可以o(1) 判断 a - c == a ^ c 是否满足,降低了一个log,复杂度为nlogn。

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>
int n,ca;
const int maxn = 3e7 + 10;
bool ispri[maxn];
int pri[maxn];
long long ans[maxn];
vector<pii> g[maxn];
int gcd(int a,int b) {
	return !b ? a : gcd(b,a % b);
}
void sieve(int n) {
	for(int i = 1; i <= n; i++) {
		for(int j = i; j <= n; j += i) {
			int c = i,a = j;
			int b = a - c;
			if((a ^ b) == c && a >= b && b > 0) {
				ans[a]++;
			}
			// c = a - b;
		}
	}
	for(int i = 1; i <= n; i++)
		ans[i] += ans[i - 1];
}
int main() {
	sieve(maxn - 1);
	scanf("%d",&ca);
	int ct = 0;
	while(ca--) {
		scanf("%d",&n);		
		printf("Case %d: %lld\n",++ct,ans[n]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41997978/article/details/89735637