UVA12716 GCD XOR(枚举)

UVA12716 GCD XOR

Description

Given an integer N, find how many pairs (A, B) are there such that: gcd(A, B) = A xor B where 1 ≤ B ≤ A ≤ N.
Here gcd(A, B) means the greatest common divisor of the numbers A and B. And A xor B is the value of the bitwise xor operation on the binary representation of A and B.

Input

The first line of the input contains an integer T (T ≤ 10000) denoting the number of test cases. The
following T lines contain an integer N (1 ≤ N ≤ 30000000).

Output

For each test case, print the case number first in the format, ‘Case X:’ (here, X is the serial of the input) followed by a space and then the answer for that case. There is no new-line between cases.
Explanation
Sample 1: For N = 7, there are four valid pairs: (3, 2), (5, 4), (6, 4) and (7, 6).

Sample Input

2
7
20000000

Sample Output

Case 1: 4
Case 2: 34866117

题解

题意

输入整数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。

代码

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;

#define REP(i,n) for(int i=0;i<(n);i++)

const int MAXN = 3e7+10;
int ans[MAXN];

void pre(){
    memset(ans,0,sizeof(ans));
    int top = MAXN >> 1,b;
    for(int c =1;c<=top;++c){
        for(int a=c+c;a<=MAXN;a+=c){
            b = a - c;
            if((a^b)==c) ++ans[a];
        }
    }
    for(int i =2;i<=MAXN;++i) ans[i]+=ans[i - 1];
}

int main(){
    pre();
    int T;
    scanf("%d",&T);
    int N;
    int kase = 0;
    while(T--){
        kase++;
        scanf("%d",&N);
        printf("Case %d: %d\n",kase,ans[N]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/caomingpei/p/9588259.html
今日推荐