uvaoj 12716 GCD XOR 打表
输入整数n(1<=n<=30000000),有多少整数对(a,b)满足1<=b<=a<=n,且gcd(a,b)=a^b=c。当n=7时,有4对,(3,2),(5,4),(6,4),(7,6).
对于异或运算,有a^b^b=a,所以可以推出,若a^b=c,则a^c=b,可以枚举a和c,算出b,验证是否有gcd(a,b)=c,注意到c是a的约数,所以,可以使用素数筛法的方法,复杂度为nlogn。
进一步可以发现,c=a-b,因为a-b<=a^b,且a-b>=c,假设存在c使得a-b>c,那么c<a-b<=a^b,这与c=a^b矛盾。
代码如下:
/*************************************************************************
> File Name: 12716.cpp
> Author: gwq
> Mail: gwq5210@qq.com
> Created Time: 2015年01月21日 星期三 21时30分29秒
************************************************************************/
#include <cmath>
#include <ctime>
#include <cctype>
#include <climits>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <algorithm>
#define INF (INT_MAX / 10)
#define clr(arr, val) memset(arr, val, sizeof(arr))
#define pb push_back
#define sz(a) ((int)(a).size())
using namespace std;
typedef set<int> si;
typedef vector<int> vi;
typedef map<int, int> mii;
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-5;
#define N 30000010
int ans[N];
int main(int argc, char *argv[])
{
int t;
int cnt = 0;
scanf("%d", &t);
for (ll c = 1; c <= N / 2; ++c) {
for (ll a = c * 2; a <= N; a += c) {
int b = a - c;
if ((a ^ b) == c) {
++ans[a];
}
}
}
for (ll c = 1; c < N; ++c) {
ans[c] += ans[c - 1];
}
while (t--) {
int n;
scanf("%d", &n);
printf("Case %d: %d\n", ++cnt, ans[n]);
}
return 0;
}