UVa 12716 (GCD == XOR)

来源:互联网 发布:定时语音播报软件 编辑:程序博客网 时间:2024/06/06 02:34
  • 题意:
    • 给定N,求二元组(A,B)的个数,满足:
    • 1<=A<=B<=NAxorB==gcd(AB)
  • 规模:

    • 1N30000000
    • T10000
  • 类型:

    • 数论,gcd
  • 分析:

    • 这里有一个规律:
    • 如果AxorB==gcd(A,B),则A-B==gcd(A,B)
    • 证明:

      • 1式:AxorB>=AB
        • 这里考虑将AB对应位数字不同的位置,交换使得,1在A里,0在B里,
        • 这样变化后异或值不变,但A-B增大。极限情况下AxorB==AB
      • 2式:gcd(A,B)<=AB ( 这个易证 )
      • 而我们有 AxorB==gcd(A,B),由12两式AxorB==(AB)==gcd(A,B)
    • 接下来,枚举gcd(A,B)(设为C)的值,A是C的倍数,看B是否符合

    • B==AxorC ==A-C
  • 代码:
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<stack>#include<math.h>#include<vector>#include<algorithm>#include<iostream>using namespace std;const int INF=0x3fff3fff;const int MAXN=3e7+10;const int MAXM=40010;const int MOD=10001;typedef long long ll;long long  n,m;//long long x[2100];int aa[MAXN];int ans[MAXN];int main(){    std::ios::sync_with_stdio(false);    std::cin.tie(0);    int T,n,a,b,c;    memset(ans,0,sizeof(ans));    memset(aa,0,sizeof(ans));    for(int i=1;i<MAXN;i++){       // cout<<i<<endl;        for(int j=2;j*i<MAXN;j++){            c=i;a=i*j;            b=c^a;//b=a-c            if(b==a-c){aa[a]++;}        }    }    for(int i=2;i<MAXN;i++){        ans[i]=ans[i-1]+aa[i];        //cout<<aa[i]<<",";    }    cin>>T;    int kase=0;    while(T--){        cin>>n;        printf("Case %d: %d\n", ++kase, ans[n]);    }    return 0;}