2016-03-29 3 views
0

Мне нужно вычислить мощность мощности. Например: 3^2^n. Вы можете считать n входным, но этот пример - это не то же самое, что и 9^n. Я пишу алгоритм с использованием циклов, но теперь мне нужно написать рекурсивный. Я не мог найти эффективный способ написать его.Рекурсивный алгоритм для мощности питания

+0

Является ли 'n' всегда положительным целым? –

+0

Да, это положительное целое число – cokomastik

+0

Можете ли вы, пожалуйста, заняться сексом? Мы не можем сделать 9^п. Можем ли мы сделать 3^(2n)? – AsafSavich

ответ

2

Допустим, х^(у^п) = powpow(x, y, n) у и п> = 1

Если у> 1 и п> 1, powpow(x, y, n) = powpow(x, y, 1) * powpow(x, y, n-1) (ближе к результату)

Если у> 1 и п = 1, powpow(x, y, 1) = x * powpow(x, y-1, 1) (ближе)

Если у = 1 и п = 1, powpow(x, 1, 1) = x (решена)

это менее эффективно, чем в цикле, но это рекурсивно. Это то, к чему вы стремитесь ...?

EDIT, как @pjs указал, первый случай должен быть: powpow(x, y, 1) = powpow(x, powpow(y, n, 1), 1)

+1

Случай, выраженный математически: 'x^y * x^(y^(n-1))', что равно «x^(y + y^(n-1))) ', а не желаемый результат 'x^(y * y^(n-1))'. – pjs

+1

@pjs хороший улов! Гош, это немного сложнее, чем я думал ... – Ilya

0
public class Power { 
    int ans = 1; 
    int z = 1; 
    int x = 1; 

    int pow1(int b, int c) { 
     if (c > 1) { 
      pow1(b, c - 1); 
     } 
     ans = ans * b; 
     return ans; 
    } 

    void pow(int a, int b, int c) { 
     x = pow1(b, c); 
     ans = a; 
     pow1(a, x - 1); 
    } 

    public static void main(String[] args) { 
     Power p = new Power(); 
     p.pow(3, 2, 3); 
     System.out.println(p.ans); 
    } 
} 
+0

Также неплохо добавить несколько строк описания к вашему ответу. Почему вы выбрали этот алгоритм, какие плюсы и минусы его и т. Д. –

+0

Для вопроса as (x^(y^n)), я сначала попытался реализовать рекурсию для (y^n), а затем использовал ответ val = (y^n), чтобы снова реализовать рекурсию для (x^val). – user6130876

0

Reccursive подход

Мы можем вычислить мощность (х, у) эффективно в сложности O (log y), используя следующие данные:

power(x, y) : 
    if y is 0 : return 1 

    if y is even : 
     return square(power(x, y/2)) 
    else : 
     return square(power(x, (y - 1)/2) * x 

Используя master theorem, мы можем вычислить сложность описанной выше процедуры как O (log y) (аналогичный случай как двоичный поиск.)

Теперь, если мы используем описанную выше процедуру для вычисления 3^(2^n).

Мы можем видеть, что (2^n) будет вычислено в O (log n) и 3^k. Где k = 2^n, будет вычисляться в O (log k) = O (log (2^n)) = O (n).

Таким образом, используя двоичный метод экспоненции последовательно, мы можем решить это с использованием сложности O (n).

Итерационный подход

Идея: Предположим, что мы вычислили 3^(2^х). Тогда мы можем легко вычислить 3^(2^(х + 1)), просто квадратуры 3^(2^х):

(3^(2^x)) * (3^(2^x)) = 3^((2^x) + (2^x)) 
            = 3^(2 * (2^x)) 
            = 3^((2^(x + 1)) 

Таким образом, если мы начинаем с 3^(2^0), в п шагов мы можем дойти до 3^(2^п):

def solve(n): 
    ans = 3^(2^0) = 3 
    for i in range(0, n) : 
     ans = square(ans) 
    return ans 

Очевидно, что сложность вышеуказанного раствора также о (п).

2

Я пошел вперед и реализовал это в Ruby, который довольно чертовски близок к псевдокоду и имеет дополнительное преимущество в том, чтобы быть проверяемым. Поскольку Ruby также имеет арифметику с произвольной точностью, следующий код работает с нетривиальными аргументами.

Эта реализация основана на старом трюке возведения в квадрат базы и повышении его до половины указанной мощности, когда показатель степени четный, поэтому рекурсивный стек растет логарифмически, а не линейно по мощности.Это был вдохновлен ответ Ильи, но я обнаружил, что y > 1 and n > 1 случай не является правильным, что приводит меня использовать рекурсивный вызов в рекурсивном вызове, реализованного в elif n > 1 строке ниже:

def powpow(x, y, n) 
    if y == 0 
    return 1 
    elsif y == 1 || n == 0 
    return x 
    elsif n > 1 
    return powpow(x, powpow(y, n, 1), 1) 
    elsif y.even? 
    return powpow(x * x, y/2, 1) 
    else 
    return x * powpow(x * x, y/2, 1) 
    end 
end 

p powpow(3,2,5) # => 1853020188851841 

Я был в состоянии подтвердить, что результат непосредственно:

irb(main):001:0> 2**5 
=> 32 
irb(main):002:0> 3**32 
=> 1853020188851841 
+0

Отлично, «старый трюк» - отличный бонус! – Ilya