什么是最有效的算法,从a ^ b的右边找到第k个数字,即从上升到幂b

时间:2015-12-17 14:27:30

标签: algorithm data-structures

我最近遇到过这个问题。我知道天真的方法,即找到一个^ b,然后提取这个数字'k'次的最低有效数字。 我正在寻找更好的方法。 'a'和'b'是整数。

4 个答案:

答案 0 :(得分:3)

a^p < 10^k时,天真的方法会中断,但a^(p+1)会溢出。只需要2*10^k-2来适应变量的解决方案是使用Russian peasant multiplication编写(a*a) mod 10^k。它通过将a和b除以2的步长来计算a*b的乘积,因此可以防止溢出,因为您可以在每个步骤之间取模数。

这是函数计算(a * b)%m的c ++实现,没有溢出:

unsigned long long abModm(unsigned long long a, unsigned long long b,unsigned long long m){
  unsigned long long res=0;
  a=a%m;
  b=b%m;
  while (b>0){
    if (b&1==1){//is b odd
      res=(res+a)%m;//collect the result
    }
    a=(a<<1)%m;//multiply a
    b>>=1;//divide b
  }
  return res;
}

然后您可以使用它来解决其他人已经建议的问题:

int kthDigit(unsigned long long a, unsigned long long b, int k){
  unsigned long long m=1;
  for (int i=0;i<k;++i) m*=10;
  unsigned long long res=1;
  for (int i=0;i<b;++i){
    res=abModm(res,a,m);
  }
  m/=10;
  return res/m;
}

指数计算是O(b)你可以用O(log(b))和

来做
unsigned long long res=1;
while (b){
  if (b&1) res=abModm(res,a,m);
  b>>=1;
  a=abModm(a,a,m);
}

答案 1 :(得分:1)

检查a可被10整除的特殊情况。如果k <1。 b结果为0,如果k≥b则为(a / 10)^ b的(k-b')数字。

计算模10 ^(k + 1)。用模10 ^(k + 1)替换a。对于64位算术,如果k≤18且a <1,则计算很容易。 2 ^ 32。

答案 2 :(得分:1)

通过逐步增加功率,并在每个步骤中丢弃不会影响您正在寻找的数字的最高位数。这将允许您超出实现的整数大小限制。在Javascript中,限制为2 53 -1,您可以计算,例如999999 999999 的第9位数字。

&#13;
&#13;
function powerDigit(a, b, k) {
    var c = 1, max = Math.pow(10, k);
    a %= max;
    while (b--) {
        c *= a;
        // if (c >= Math.pow(2, 53)) return NaN; // Javascript limitation
        c %= max;
    }
    return Math.floor(c * 10 / max);
}

document.write(powerDigit(9, 9, 9) + "<BR>");     // 3 ; 387420489
document.write(powerDigit(99, 9, 9) + "<BR>");    // 4 ; 913517247483640899
document.write(powerDigit(99, 99, 9) + "<BR>");   // 2 ; 3.697296376497267726e+197
document.write(powerDigit(999, 999, 9) + "<BR>"); // 4 ; 3.680634882592232678e+2996
document.write(powerDigit(999999, 999999, 9));    // 9 ; millions of digits
&#13;
&#13;
&#13;

答案 3 :(得分:0)

首先你需要找到一个^ b然后你将它除以10 ^(k-1),然后从你得到模数10的结果中得到你的第k个数字。 这里我给出c代码的例子:

double r=pow(a,b)/pow(10,k-1);
   int result=(int)r%10;