zoukankan      html  css  js  c++  java
  • UVA.12716 GCD XOR (暴力枚举 数论GCD)

    UVA.12716 GCD XOR (暴力枚举 数论GCD)

    题意分析

    题意比较简单,求[1,n]范围内的整数队a,b(a<=b)的个数,使得 gcd(a,b) = a XOR b.

    前置技能

    XOR的性质
    GCD

    由于题目只给出一个n,我们要求对数,能做的也始终暴力枚举a,b,这样就有n^2的复杂度,由于n很大,根本过不了。

    于是我们就想用到其中一些性质,如XOR 与GCD,不妨假设 a xor b = c,并且根据题意还知道, gcd(a,b) = c,也就说明c一定是a的因子,所以在枚举的时候,可以转过头来枚举a和c.那么如何求出当前情况下的b呢,考虑到xor的性质,即 a xor b = c, a xor c = a xor a xor b = b. 通过异或运算就可以求解出来b,然后再检验gcd(a,b)是否为c即可。

    到这里其实已经足够了,但是打出一定规模符合题意的(a,b,c),不难发现,a-b=c,有了这条性质,就可以不用gcd检验了。换句话说,通过枚举a,c,b = a-c计算出b,通过a^b=c检验是否符合条件。因为相对而言,位运算比gcd快得多。

    值得一提的是,由于n很大,连续处理多个n很大的值的时候,速度表现不能令人满意,最先想到的办法就是打表方法。

    代码总览

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <cmath>
    #define nmax 30000010
    #define ll long long
    using namespace std;
    int n;
    int t;
    int num[nmax];
    
    void init(){
        for(int c = 1;c<=(nmax+1)/2;++c){
            for(int a = c+c;a<nmax;a+=c){
                int b = a-c;
                if((a^b) == c) num[a]++;
            }
        }
        for(int i = 2;i<nmax;++i)  num[i]+=num[i-1];
    }
    
    int main()
    {
        int kase =1 ;
        init();
        scanf("%d",&t);
        for(kase  = 1; kase <=t;++kase){
            scanf("%d",&n);
            printf("Case %d: %d
    ",kase,num[n]);
        }
        return 0;
    }
  • 相关阅读:
    Java常用类库--观察者设计模式( Observable类Observer接口)
    Android EditText的设置
    动态更换view类的背景----StateListDrawable的应用
    Android studio之更改快捷键及自动导包
    Android利用广播监听设备安装和卸载应用程序
    Java的socket服务UDP协议
    1037. Magic Coupon (25)
    JSP标签
    oracle 打开trace,并分析trace
    从Java到C++——从union到VARIANT与CComVariant的深层剖析
  • 原文地址:https://www.cnblogs.com/pengwill/p/7367023.html
Copyright © 2011-2022 走看看