【问题标题】:Check for a number to be a ** b检查数字是否为 a ** b
【发布时间】:2014-01-04 16:06:27
【问题描述】:

我的问题是编写一个有效的算法来检查给定数字 n 是否为 ab 形式,其中 a, b 是整数 >= 2。我尝试了以下方法,但时间效率不高。

int cnt = 0;
long long i, sq = sqrt(n);
for (i = 2; i <= sq; i++) {
    if (n % i == 0) {
        cnt++;
        n = n / i;
        while (n % i == 0) {
            n /= i;
            cnt++;

        }
        if (n == 1) {
            break;
        }
    }
}
if (cnt >= 2) {
    return true;
}
return false;

【问题讨论】:

  • 嗯,XOR 是一个可逆运算,所以这应该很容易......
  • @biziclop 问题被标记为 C/C++,^ 在这些语言中将是 XOR
  • 另外你的实现似乎是错误的,它给了我true for n=12
  • 是的,实现不仅慢而且错误。事实上,一旦你找到了任何除数,你就永远不应该回到除数搜索循环(为什么?)

标签: c algorithm math


【解决方案1】:

我假设您的意思是 pow(a, b) 不是 a^b,因为 C/C++ 中的 ^XOR 运算符。

您的问题被称为检测perfect powers,您可以在互联网上找到很多文献。

例如:Detecting perfect powers in linear time Daniel Bernstein。

【讨论】:

    【解决方案2】:

    您可以通过替换来修复代码并显着加快代码速度:

    if (n == 1) break;
    

    return (n == 1);
    

    那么既然你不厌其烦地计算sqrt(n),还不如早点退出完美平方:

    if (n == sq * sq) return true;
    

    【讨论】:

      【解决方案3】:

      想法:

      if n = 3^5 then:
           ln(n) / ln(3)   = 5
      exp( ln(n) /    5  ) = 3
      

      示例 JavaScript 代码,打开检查器/控制台查看结果(可轻松转换为 C):

      http://jsfiddle.net/8wuUK/

      function powerSplit( n ){
        console.log('n =', n);
        var log = Math.log, exp = Math.exp, abs = Math.abs,
            floor = Math.floor, round = Math.round;
        var epsilon = 0.001;
        var logn = log( n );
        var pow = floor( log(n) / log(2) ) + 1;
        do{
          pow --;
          var base = exp( logn / pow );
          var intbase = round( base );
          if( abs( base - intbase ) > epsilon ) continue;
          //console.log( base, intbase, pow, isExactPower( n, intbase ) );
          if( isExactPower( n, intbase ))  return 'n = ' + intbase +' ^ ' + pow;
        }while( pow >= 1 );
        return 'n is not a power';
      }
      
      function isExactPower( n, base ){
        while( n > 1 ){
          if( n % base ) return false;
          n /= base;
        };
        return true;
      };
      

      【讨论】:

        猜你喜欢
        • 2014-05-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-10
        • 2013-07-28
        • 2017-09-04
        • 1970-01-01
        • 2023-04-05
        • 2016-10-10
        相关资源
        最近更新 更多