码迷,mamicode.com
首页 > 其他好文 > 详细

GCD和XOR题解

时间:2019-08-26 18:08:44      阅读:92      评论:0      收藏:0      [点我收藏+]

标签:std   ++   print   简单的   color   枚举   二进制   scanf   include   

由题意

我们要统计1~N中有多少二元组(a,b)满足gcd(a,b) ==a XOR b


 

首先有如下性质

1.a XOR b >= a-b  (a >= b)

证明:(给个简单的证明 OI证明都不严谨的)

在二进制下

  a XOR b :b某一位的1才对答案有影响,如果a那位为1那就相当于减,为0相当于加

  a 减     b: 同样b的某一为的1才对答案影响,且a的那一位不管是0还是1,都是减

所以 a XOR b 一定 >= a-b

2. a - b >= gcd( a,b )

证明:

设gcd(a,b)=c

则a=c*x1,b=c*x2(x1,x2互质且大于等于1)x1>=x2

a - b = c*(x1 -x2)>= c


 

所以a XOR b >= a-b >= gcd(a,b)

而  a  XOR b=gcd(a,b)

所以a XOR b = a - b = gcd (a,b) 


 

到这里解法应该就有很多了,我只分享第一次想到的

令 gcd(a,b)=d,a=d*x1 ,b=d*x2

由上述等式得x1-x2=1;

所以我们外层枚举d,内层枚举b,(a直接得到),然后判断a XOR b 是否等于 a  - b

代码如下

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e7;
 4 int c[N+9];//c[i]表示i与1~i-1中共有多少对满足 
 5 void pre(){
 6     for(int d=1;d<=N;d++){
 7         for(int b=d;b<=N-d;b+=d){
 8             int a=b+d;
 9             if((a^b)==(a-b))c[a]++;
10         }
11     }
12     for(int i=1;i<=N;i++)c[i]+=c[i-1];//求出前缀和 
13 }
14 void work(){
15     int T,n;
16     scanf("%d",&T);
17     for(int i=1;i<=T;i++){
18         scanf("%d",&n);
19         printf("Case %d: %d\n",i,c[n]);
20     }
21 }
22 int main(){
23     pre();
24     work();
25     return 0;
26 } 

 

GCD和XOR题解

标签:std   ++   print   简单的   color   枚举   二进制   scanf   include   

原文地址:https://www.cnblogs.com/zrqlj/p/11413986.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!