原题链接:点击打开链接
题意:输入整数n(1<=n<=3千万),有多少对整数(a,b)满足:1<=b<=a<=n,且gcd(a,b)=a XOR b。例如:n=7时,有4对:(3,2),(5,4),(6,4),(7,6)。
思路:
有几个结论:(1)若 a xor b = c,则 a xor c = b。
(2)a - b <= a xor b,(a >= b)
(3)若 gcd(a,b)= a xor b = c ,(a >= b),由(2)得:a - b <= c。
再令 a = k1×c,b = k2 × c,(k1 >= k2),所以 a - b = (k1 - k2)× c,所以 a - b >= c。总:a - b = c
(这里若k1 = k2,那么 a = b,那么 a xor b = 0)
然后就是怎么枚举的问题了,要保证计算量尽量小,如果枚举a,就要枚举a的所有因数,有些数因为可能是多个数的因数,会被重复考虑很多次。所以这里要枚举因数 c ,a = k × c(k >= 2) 这样每个因数只枚举一遍,再检验b。
/*************************************************************************
> File Name: 12716.cpp
> Author: Clannad
> Mail: 821199012@qq.com
> Created Time: Mon 11 July 2016 02:31:33 PM
************************************************************************/
#include <vector>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include<string>
#include <ctime>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=3e7;
int ans[maxn+5];
int T,n,Case=0;
void init(){
int top=maxn>>1;
int b;
for(int c=1 ; c<=top ; c++){
for(int a=c+c ; a<=maxn ; a+=c){
b=a-c;
if(c==(a^b))ans[a]++;
}
}
for(int i=2 ; i<=maxn ; i++)
ans[i]+=ans[i-1];
}
int main()
{
std::ios::sync_with_stdio(false);
// #ifndef ONLINE_JUDGE
// freopen("inE.txt", "r", stdin);
// #endif
init();
cin>>T;
while(T--){
cin>>n;
printf("Case %d: %d\n",++Case,ans[n]);
}
return 0;
}