Uva12716Gcd=Xor

题意:

求满足GCD(a,b) = a XOR b; 其中1<=b <=a<=n。1<= n <= 30000000.

思路:

异或:a XOR b = c 那么 a XOR c = b;
那么我们令GCD(a,b)= c; 这样 a 是 c 倍数。我们可以通过遍历c , 然后通过筛法,把c的倍数晒出当作a。求b如何求呢?

书上提供一种方法是利用a XOR c=b 然后用 gcd(a,b)=c 验证。但是这个方法是超时的,gcd是logn 级别的 总的时间复杂度,n*(logn)^2。这是我们不能接受的。

还有一种方法是证明b=a-c。这个证明还是不容易的 :

首先(a>b)gcd(a,b) = c <= a-b 其次要证明a ^ b >= a-b 。我们可以这样想,他们什么时候取等于,我们知道异或是相同为0,不同为1 那么 我们把a,b用二进制展开,这样我们a,b是每一位对应的,我们把所以不同的二进制位,全部变为ai = 1,bi = 0。这样我们知道,没有借位 那么a ^ b == a-b 。那么后面按照XOR序列的顺序变化,a-b变小,那么a ^ b >= a-b。从而c = a-b
参考:http://www.mamicode.com/info-detail-2490991.html

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
//#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int RA = 30000000;

int ans[RA + 5];

void Init(){
	memset(ans,0,sizeof(ans));
    for(int c = 1; c <= RA/2; ++c){
        for(int a = c + c; a <= RA; a += c){
            int b = a - c;
            if((a ^ b) == c) ++ans[a];
        }
    }
    for(int i = 2; i <= RA; ++i) ans[i] += ans[i - 1];
}

int main(){
	
    Init();
    //freopen("in.txt","r",stdin);
    int T,N; 
    scanf("%d",&T);
    for(int i = 1; i <= T; ++i){
        scanf("%d",&N);
        printf("Case %d: %d\n",i,ans[N]);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值