UVA 12716 GCD XOR (异或)

题意:求出[1,n]中满足gcd(a,b)=a xor b,且1<=a<=b<=n的对数

题解:首先a xor b = c,则a xor c = b,而b是a的约数,则可以使用素数筛选法的方法使用O(nlogn)枚举a与c

       接着gcd需要O(logn)的时间,时间为O(n(logn)^2)

    但是我们还可以继续优化掉一个log,我们打表找规律可以看出c=a-b

   证明:因为a - b(相同为0,不同为1或者-1) <=a xor b(相同为0,不同为1),又因为gcd(a,b)=c,所以a-b>=c

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<string>
#include<cstdio>
#include<cstring>
#include<iomanip>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define eps 1E-8
/*注意可能会有输出-0.000*/
#define sgn(x) (x<-eps? -1 :x<eps? 0:1)//x为两个浮点数差的比较,注意返回整型
#define cvs(x) (x > 0.0 ? x+eps : x-eps)//浮点数转化
#define zero(x) (((x)>0?(x):-(x))<eps)//判断是否等于0
#define mul(a,b) (a<<b)
#define dir(a,b) (a>>b)
typedef long long ll;
typedef unsigned long long ull;
const int Inf=1<<28;
const ll INF=1LL<<60;
const double Pi=acos(-1.0);
const int Mod=1e9+7;
const int Max=30000010;
int ans[Max];
void Init(int n)
{
    memset(ans,0,sizeof(ans));
    for(int c=1;c<n;++c)
    {
        for(int a=c+c;a<n;a+=c)
        {
            if(a-c==(a^c))
                ans[a]++;
        }
    }
    for(int i=1;i<n;++i)
    {
        ans[i]+=ans[i-1];
    }
    return ;
}
int main()
{
    Init(30000001);
    int t,n,coun=0;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        printf("Case %d: %d\n",++coun,ans[n]);
    }
    return 0;
}
时间: 2024-12-13 15:58:49

UVA 12716 GCD XOR (异或)的相关文章

UVA 12716 GCD XOR【异或】

参考:http://www.cnblogs.com/naturepengchen/articles/3952145.html #include<stdio.h> #include<string.h> #include<time.h> const int N=3e7+11; int ans[N]; int gcd(int a,int b){ if(!b) return a; return gcd(b,a%b); } void init(){ for(int c=1;c&l

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 -

UVa 12716 (GCD == XOR) GCD XOR

题意: 问整数n以内,有多少对整数a.b满足(1≤b≤a)且gcd(a, b) = xor(a, b) 分析: gcd和xor看起来风马牛不相及的运算,居然有一个比较"神奇"的结论: 设gcd(a, b) = xor(a, b) = c, 则 c = a - b 这里 有比较严格的证明. 有了这个结论后,我们可以枚举约数c,然后枚举c的倍数a,再根据c = a - b计算b,检验b是否满足gcd(a, b) = xor(a, b) 1 #include <cstdio> 2

UVa 12716 GCD XOR (简单证明)

题意: 问 gcd(i,j) = i ^ j  的对数(j <=i <= N ) N的范围为30000000,有10000组例子 思路:GCD(a,b) = a^b = c GCD(a/c,b/c) = 1 (1) (a-b) <= c (2) (a/c-b/c) <=1 (3) (1)(3) => a/c-b/c = 1=> a-b=c #include <iostream> #include <cstdio> #include <cst

【UVA】12716-GCD XOR

做出做道题需要注意2个地方: 首先可以打表找规律,找到规律我们可以发现: 1.如果gcd(a,b) = a ^ b = c,那么 b = a - c; 既然这样我们可以枚举a,c,求出b之后判断 c 是否等于 a ^ b,那么如何枚举c呢? 2.利用类似筛选素数的方法去枚举a,c 首先c是a的约数,所以这道题我们需要枚举的其实是a的约数,但是约数也不好枚举,我们可以通过c去枚举a,我们通过枚举c,找到约数是c的所有a. 这题由于数据过大,需要打表,否则超时. 14024658 12716 GCD

hdu 5175 Misaki&#39;s Kiss again(GCD和异或)

题意: 给一个数N. 如果GCD(N,M) = N XOR M,则称M是一个kiss   1<=M<=N 问总共有多少个kiss.并且列出所有的值. 思路: 思路一:枚举M.有大量的GCD(N,M)值相等.但是N XOR M=X.当X是定值是,M一定只有一个.所以这个方法明显有大量重复. 发现知道GCD(N,M)的值,可直接求出M.搞定. 令gcd(n,m)=d,可知道d是n的约数 有d=(n xor m)=(m xor n),所以m=(d xor n). 可发现gcd(n,(d xor n)

【Math】GCD XOR 证明

题目:Given an integer N, and how many pairs (A;B) are there such that: gcd(A;B) = A xor B where 1<=B<=A<=N. 首先先爆一发,妥妥超时.其实真相是我想打表找规律.结果没什么规律可循. 后来分析:要想让GCD(A,B)==(A^B),A和B一定是同样的位数(二进制).因此打表方法可变为:(亦超时) void init() { int K=0; int last=0; for(int i=1;

uva 1521 - GCD Guessing Game(贪心)

题目链接:uva 1521 - GCD Guessing Game 题目大意:给定一个数N,现在又一个数x,在1~N之间,现在每次可以猜一个数a,返回gcd(x,a),问说最少猜几次可以确定x. 解题思路:其实就将1~N里面的素数都要考虑一遍,因为有一个N的限制,所以每次选出来的素数的积不大于N即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const

Uva 11388 GCD LCM ( 数论 )

Uva  11388 GCD LCM( 数论 ) 题意: 求是否存在a,b 使得lcm(a,b) = L, gcd(a,b) = G,不存在输出-1,存在输出a,b,且a尽可能小 分析: 强行暴力是不可能的数据很大,要用llu,这里有两种思路 思路一: 由题意可知 a*b = G*L 保证a = G的倍数的情况下,枚举a再判断G*L能否整除a,最后判断b是否为a的倍数.a从G开始扫到sqrt(G*L) //输入两个整数G,L //找出a,b 使得 gcd(a,b) = G lcm(a,b) =