首页 > 代码库 > UVA 12716 GCD XOR(数论+枚举+打表)

UVA 12716 GCD XOR(数论+枚举+打表)

??

题意:给你一个N,让你求有多少组A,B,  满足1<= B <= A <= N, 且 gcd(A,B) = A XOR B。

思路:首先我们能够得出两个结论:

A-B >= A%B >= gcd(A, B)

A xor B >= A-B

所以说A xor B >= A-B >= gcd(A, B),然后就能够推出 

A xor B = A - B = gcd(A, B) =>    A xor B = A - B  &&  A - B = gcd(A, B)

设 C = gcd(A, B),那么我们能够枚举C和A。通过A-C求出B,再验证A xor B 是否等于C就可以

这里的枚举是仿照筛素数的方法,对于每个A。我们求出一共同拥有多少C满足条件,记为ans[A],那么最后仅仅须要累加一下就能够。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<stack>
#include<string>
#include<map>
#include<set>
#include<ctime>
#define eps 1e-6
#define LL long long
#define pii (pair<int, int>)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int maxn = 30000000 + 10000;
//const int INF = 0x3f3f3f3f;
int n;
int ans[maxn];

void init() {
	for(int c = 1; c <= 30000000; c++) {
		for(int a = c<<1; a <= 30000000; a += c) {
			int b = a - c;
			if((a^b) == a-b) ans[a]++;
		}
	}
	for(int i = 1; i <= 30000000; i++) ans[i] += ans[i-1];
}

int main() {
    //freopen("input.txt", "r", stdin);
	int T; cin >> T;
	int kase = 0;
	init();
	while(T--) {
		scanf("%d", &n);
		printf("Case %d: %d\n", ++kase, ans[n]);
	}
    return 0;
}





UVA 12716 GCD XOR(数论+枚举+打表)