[关闭]
@BIGBALLON 2015-03-19T08:42:34.000000Z 字数 1189 阅读 1449

Integer’s Power

acm


  • 题意:Integer’s Power
    给定区间 [l,r] ,求改区间中能够表示为x^k( x尽量小, k尽量大 )的数的个数
  • 问题转化:
    转化为求区间 [1,l-1][1,r] 的个数,两数相减便是答案
  • 分析:
    题目中 (2 <= a <= b <= 10^18 < 2^62 )
    因此我们可以从指数2开始枚举到62
    对于k=1的情况我们单独考虑
    i为指数大小,num[i]为指数对应的个数减1
    num[1] = n,表示所有数均有指数为1的情况(把1的power值也看为1)
    通过使用pow( n, 1.0/k )
    可以求出指数为k的数的个数
    但是这并不一定是满足要求的数,比如64=2^6=8^2 就会出现重复计数。
    我们再通过容斥原理来去除重复。
    最后累加i*num[i]得到答案
  • 注意:
    1. 使用r = pow( x, 1.0/k )会产生精度误差
      这时我们再计算(r-1)^k r^k (r+1)^k,寻找最接近x的值所对应的r
    2. 同时在计算(r+1)^k的时候还可能会造成溢出
      所以在fast_pow函数中要进行相应处理
    代码君
  1. #include <cstdio>
  2. #include <cmath>
  3. using namespace std;
  4. typedef long long LL;
  5. const LL INF = 1e18 + 233;
  6. const LL T = ( LL ) 1 << 31;
  7. LL num[62], l, r;
  8. LL fast_pow( LL a, LL b )
  9. {
  10. LL ans = 1;
  11. while( b )
  12. {
  13. if( b & 1 )
  14. {
  15. double t = 1.0 * (INF)/ans;
  16. if( a > t ) return -1;
  17. ans = ans * a;
  18. }
  19. b >>= 1;
  20. if( a > T && b > 0 ) return -1;
  21. a = a * a;
  22. }
  23. return ans;
  24. }
  25. LL find( LL x, LL y )
  26. {
  27. LL r = ( LL )pow( x, 1.0/y );
  28. LL t, p;
  29. p = fast_pow( r, y );
  30. if( p == x ) return r;
  31. if( p > x || p == -1 ) r--;
  32. else
  33. {
  34. t = fast_pow( r+1, y );
  35. if( t != -1 && t <= x ) r++;
  36. }
  37. return r;
  38. }
  39. LL solve( LL n )
  40. {
  41. int s;
  42. for( int i = 0; i < 62; ++i )
  43. num[i] = 0;
  44. if( n <= 3 ) return n;
  45. num[1] = n;
  46. for( s = 2; s < 63; ++s )
  47. {
  48. num[s] = find( n, s ) - 1;
  49. if( !num[s] ) break;
  50. }
  51. for( int i = s - 1; i > 0; --i )
  52. for( int j = 1; j < i; ++j )
  53. if( i % j == 0 )
  54. num[j] -= num[i];
  55. LL ans = num[1];
  56. for( int i = 2; i < s; ++i )
  57. ans += ( i * num[i] );
  58. return ans;
  59. }
  60. int main()
  61. {
  62. while( ~scanf( "%I64d %I64d", &l, &r ) && ( l + r ) )
  63. {
  64. printf( "%I64d\n", solve(r) - solve( l - 1 ) );
  65. }
  66. return 0;
  67. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注