Uva--12716(数论,枚举,xor)
2014-09-02 19:13:32
12716 GCD XOR
题意:输入整数n(1<=n<=3千万),有多少对整数(a,b)满足:1<=b<=a<=n,且gcd(a,b)=a XOR b。例如:n=7时,有4对:(3,2),(5,4),(6,4),(7,6)。
思路:第二版小白书例题,但是前两次交都是TLE。。。借鉴书里和别人的博客
有几个结论:(1)若 a xor b = c,则 a xor c = b。
(2)a - b <= a xor b,(a >= b)
(3)若 gcd(a,b)= a xor b = c ,(a >= b),由(2)得:a - b <= c。
再令 a = k1×c,b = k2 × c,(k1 >= k2),所以 a - b = (k1 - k2)× c,所以 a - b >= c。总:a - b = c
(这里若k1 = k2,那么 a = b,那么 a xor b = 0)
然后就是怎么枚举的问题了,要保证计算量尽量小,如果枚举a,就要枚举a的所有因数,有些数因为可能是多个数的因数,会被重复考虑很多次。所以这里要枚举因数 c ,a = k × c(k >= 2) 这样每个因数只枚举一遍,再检验b。
1 /************************************************************************* 2 > File Name: 12716.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Tue 02 Sep 2014 04:17:33 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <iostream> 13 #include <algorithm> 14 using namespace std; 15 typedef long long ll; 16 const int RA = 30000000; 17 18 int T,N; 19 int ans[RA + 5]; 20 21 void Init(){ 22 int top = RA >> 1,b; 23 for(int c = 1; c <= top; ++c){ 24 for(int a = c + c; a <= RA; a += c){ 25 b = a - c; 26 if((a ^ b) == c) ++ans[a]; 27 } 28 } 29 for(int i = 2; i <= RA; ++i) ans[i] += ans[i - 1]; 30 } 31 32 int main(){ 33 Init(); 34 scanf("%d",&T); 35 for(int t = 1; t <= T; ++t){ 36 scanf("%d",&N); 37 printf("Case %d: %d\n",t,ans[N]); 38 } 39 return 0; 40 }