Как проверить, является ли целое число 3?

Я видел этот вопрос и высказывал эту идею.

Ответ 1

while (n % 3 == 0) {
    n /= 3;
}
return n == 1;

Заметим, что 1 - это нулевая степень трех.

Изменить: Вам также нужно проверить нуль перед циклом, так как цикл не будет прерван для n = 0 (спасибо Бруно Ротгиссер).

Ответ 2

Существует метод с постоянным временем (довольно быстрый) для целых чисел с ограниченным размером (например, 32-разрядные целые числа).

Обратите внимание, что для целых N, которые являются степенью 3, верно следующее:

  • Для любого M <= N, который является степенью 3, M делит N.
  • Для любого M <= N, не являющегося степенью 3, M не делит N.

Самая большая мощность 3, которая вписывается в 32 бита, составляет 3486784401 (3^20). Это дает следующий код:

bool isPower3(std::uint32_t value) {
    return value != 0 && 3486784401u % value == 0;
}

Аналогично для подписанных 32 бит это 1162261467 (3^19):

bool isPower3(std::int32_t value) {
    return value > 0 && 1162261467 % value == 0;
}

В общем случае магическое число:

3^floor(log_3 MAX)== pow(3, floor(log(MAX) / log(3)))

Осторожно с ошибками округления с плавающей запятой, используйте математический калькулятор, например Wolfram Alpha для вычисления константы. Например, для 2^63-1 (подписанный int64) и С++, и Java дают 4052555153018976256, но правильное значение 4052555153018976267.

Ответ 3

Я немного задумываюсь, что если по 'integer' вы имеете в виду "подписанное 32-битное целое число", то (псевдокод)

return (n == 1) 
    or (n == 3)
    or (n == 9)
    ... 
    or (n == 1162261467) 

имеет для него некоторую красивую простоту (последнее число равно 3 ^ 19, поэтому не существует абсурдного числа случаев). Даже для 64-битного целого числа без знака все еще остается только 41 случай (спасибо @Alexandru за то, что он указал мой промах). И, конечно, было бы невозможно для арифметики с произвольной точностью...

Ответ 4

Я удивлен этим. Каждый, кажется, пропустил самый быстрый алгоритм для всех.

Следующий алгоритм в среднем быстрее - и в некоторых случаях значительно быстрее - чем простой цикл while(n%3==0) n/=3;:

bool IsPowerOfThree(uint n)
{
  // Optimizing lines to handle the most common cases extremely quickly
  if(n%3 != 0) return n==1;
  if(n%9 != 0) return n==3;

  // General algorithm - works for any uint
  uint r;
  n = Math.DivRem(n, 59049, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r, 243, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r,  27, out r); if(n!=0 && r!=0) return false;
  n += r;
  return n==1 || n==3 || n==9;
}

Числовые константы в коде 3 ^ 10, 3 ^ 5 и 3 ^ 3.

Эксплуатационные расчеты

В современных процессорах DivRem является часто одной инструкцией, которая занимает один цикл. На других он расширяется до div, за которым следует mul и add, что в целом будет больше трех циклов. Каждый шаг общего алгоритма выглядит длинным, но на самом деле он состоит только из: DivRem, cmp, cmove, cmp, cand, cjmp, add. Существует много доступных parallelism, поэтому на типичном двухстороннем суперскалярном процессоре каждый шаг, вероятно, будет выполняться примерно в 4 тактовых циклах, обеспечивая гарантированное наихудшее время выполнения около 25 тактов.

Если входные значения равномерно распределены в диапазоне UInt32, вот вероятности, связанные с этим алгоритмом:

  • Возврат в или перед первой оптимизирующей линией: 66% времени
  • Возврат в или до второй линии оптимизации: 89% времени
  • Возврат в первом шаге алгоритма или перед ним: 99,998% времени
  • Возврат во втором или втором шаге алгоритма: 99.99998% времени
  • Возврат в третьем или третьем шаге алгоритма: 99.999997% времени

Этот алгоритм превосходит простой цикл while(n%3==0) n/=3, который имеет следующие вероятности:

  • Возврат на первой итерации: 66% времени
  • Возврат в первых двух итерациях: 89% времени
  • Возврат в первые три итерации: 97% времени
  • Возврат в первые четыре итерации: 98.8% времени
  • Вернитесь в первые пять итераций: 99.6% времени... и так далее...
  • Вернитесь в первые двенадцать итераций: 99.9998% времени... и далее...

Что еще более важно, этот алгоритм более эффективно обрабатывает средние и большие мощности трех (и их кратность) намного: в худшем случае простой алгоритм будет потреблять более 100 циклов ЦП, поскольку он будет цикл 20 раз (41 раз для 64 бит). Приведенный здесь алгоритм никогда не займет больше 25 циклов.

Расширение до 64 бит

Расширение вышеуказанного алгоритма до 64 бит тривиально - просто добавьте еще один шаг. Вот 64-битная версия алгоритма, оптимизированная для процессоров без эффективного 64-разрядного деления:

bool IsPowerOfThree(ulong nL)
{
  // General algorithm only
  ulong rL;
  nL = Math.DivRem(nL, 3486784401, out rL); if(nL!=0 && rL!=0) return false;
  nL = Math.DivRem(nL+rL,   59049, out rL); if(nL!=0 && rL!=0) return false;
  uint n = (uint)nL + (uint)rL;
  n = Math.DivRem(n,   243, out r); if(n!=0 && r!=0) return false;
  n = Math.DivRem(n+r,  27, out r); if(n!=0 && r!=0) return false;
  n += r;
  return n==1 || n==3 || n==9;

}

Новая константа 3 ^ 20. Линии оптимизации опущены в верхней части метода, потому что в нашем предположении, что разделение 64 бит медленное, они фактически замедляют работу.

Почему этот метод работает

Скажем, я хочу знать, является ли "100000000000000000" мощностью 10. Я мог бы выполнить следующие шаги:

  • Я делю на 10 ^ 10 и получаю коэффициент 10000000 и остаток 0. Они добавляют к 10000000.
  • Я делюсь на 10 ^ 5 и получаю коэффициент 100 и остаток 0. Они добавляют к 100.
  • Я делю на 10 ^ 3 и получаю коэффициент 0 и остаток 100. Они добавляют к 100.
  • Я делю на 10 ^ 2 и получаю частное от 1 и остаток от 0. Они добавляют к 1.

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

В этом примере я выбрал показатели 10, 5 и 3, чтобы соответствовать ранее предоставленному коду, и добавил 2 только для него. Другие экспоненты также будут работать: существует простой алгоритм для выбора идеальных показателей с учетом вашего максимального входного значения и максимальной мощности 10, разрешенных на выходе, но на этом поле не хватает места для его размещения.

ПРИМЕЧАНИЕ. Возможно, вы думали в базе десять в этом объяснении, но все объяснение, приведенное выше, можно прочитать и понять одинаково, если вы думаете в третьей главе, за исключением того, что экспоненты были бы выражены по-разному (вместо "10", "5", "3" и "2", я должен был бы сказать "101", "12", "10" и "2" ).

Ответ 5

если (log n)/(log 3) является интегралом, то n является степенью 3.

Ответ 6

Рекурсивно разделить на 3, проверить, что остаток равен нулю и повторно применить к частному.

Обратите внимание, что 1 является допустимым ответом, так как 3 к нулевой мощности равно 1 - это крайний случай, чтобы остерегаться.

Ответ 7

Очень интересный вопрос, мне нравится ответ от starblue, и это вариация его алгоритма, который быстрее сходится к решению:

private bool IsPow3(int n)
{
    if (n == 0) return false;
    while (n % 9 == 0)
    {
        n /= 9;
    }
    return (n == 1 || n == 3);
}

Ответ 8

Между степенями двух есть не более одной степени из трех. Итак, следующее быстрое испытание:

  • Найдите двоичный логарифм n, найдя позицию ведущего бита 1 в номере. Это очень быстро, так как современные процессоры имеют для этого специальную инструкцию. (В противном случае вы можете сделать это с помощью бит-twiddling, см. Бит-твист-хаки).

  • Посмотрите на потенциальную мощность трех в таблице, проиндексированной этой позицией, и сравните ее с n (если нет мощности в три, вы можете сохранить любое число с другим двоичным логарифмом).

  • Если они равны, верните да, иначе нет.

Время выполнения зависит в основном от времени, необходимого для доступа к записи в таблице. Если мы используем машинные целые числа, таблица небольшая и, вероятно, в кеше (мы используем ее много миллионов раз, в противном случае этот уровень оптимизации не имеет смысла).

Ответ 9

Простое и постоянное решение:

return n == power(3, round(log(n) / log(3)))

Ответ 10

Насколько велика ваша вкладка? С O (log (N)) памятью вы можете делать быстрее, O (log (log (N)). Прекоммутируйте полномочия 3, а затем выполните двоичный поиск по предварительно вычисленным значениям.

Ответ 11

Для действительно больших чисел n вы можете использовать следующий математический трюк, чтобы ускорить работу

  n % 3 == 0

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

Пусть x = Sigma; k a k 2 k - номер интереса. Мы можем допустить, что верхняя граница суммы равна & infin; с пониманием, что a k= 0 для некоторого k > M. Тогда

0 & equiv; x & equiv; &Сигма; k a k 2 k & equiv; &Сигма; k a 2k 2 2k + a 2k + 1 2 2k + 1 & equiv; &Сигма; k 2 2k (a 2k + a 2k + 1 2) & equiv; &Сигма; k a 2k + a 2k + 1 2 (mod 3)

так как 2 2k & equiv; 4 k & equiv; 1 k & equiv; 1 (mod 3).

Учитывая двоичное представление числа x с 2n + 1 битами как

x 0 x 1 x 2... x 2n + 1

где x k & isin; {0,1}, вы можете группировать нечетные четные пары

(x 0 x 1) (x 2 x 3)... (x 2n x 2n + 1).

Обозначим через q число спариваний вида (1 0), а через r обозначим число спариваний вида (0 1). Тогда из приведенного выше уравнения следует, что 3 | х тогда и только тогда, когда 3 | (q + 2r). Кроме того, вы можете показать, что 3 | (q + 2r) тогда и только тогда, когда q и r имеют одинаковый остаток при делении на 3.

Таким образом, алгоритм определения того, делится ли число на 3, можно сделать следующим образом:

 q = 0, r = 0
 for i in {0,1, .., n}
     pair <- (x_{2i} x_{2i+1})
     if pair == (1 0)
         switch(q)
             case 0:
                 q = 1;
                 break;
             case 1:
                 q = 2;
                 break;
             case 2:
                 q = 0;
                 break;
     else if pair == (0 1)
         switch(r)
             case 0:
                 r = 1;
                 break;
             case 1:
                 r = 2;
                 break;
             case 2:
                 r = 0;
 return q == r

Этот алгоритм более эффективен, чем использование%.

--- Редактировать много лет спустя ----

Я потратил несколько минут, чтобы реализовать рудиментарную версию этого в python, которая проверяет его истинность для всех чисел до 10 ^ 4. Я включаю его ниже для справки. Очевидно, чтобы использовать это, можно было бы реализовать это как можно ближе к оборудованию. Эта технология сканирования может быть расширена до любого числа, которое требуется, путем изменения вывода. Я также предполагаю, что часть "сканирования" алгоритма может быть переформулирована в рекурсивной формулировке типа O(log n), подобной БПФ, но я должен подумать об этом.

#!/usr/bin/python

def bits2num(bits):
    num = 0
    for i,b in enumerate(bits):
        num += int(b) << i
    return num

def num2bits(num):
    base = 0
    bits = list()
    while True:
        op = 1 << base
        if op > num:
            break
        bits.append(op&num !=0)
        base += 1
    return "".join(map(str,map(int,bits)))[::-1]

def div3(bits):

    n = len(bits)

    if n % 2 != 0:
        bits = bits + '0'

    n = len(bits)

    assert n % 2 == 0

    q = 0
    r = 0
    for i in range(n/2):
        pair = bits[2*i:2*i+2]
        if pair == '10':
            if q == 0:
                q = 1
            elif q == 1:
                q = 2
            elif q == 2:
                q = 0
        elif pair == '01':
            if r == 0:
                r = 1
            elif r == 1:
                r = 2
            elif r == 2:
                r = 0
        else:
            pass

    return q == r

for i in range(10000):
    truth = (i % 3)  == 0
    bits = num2bits(i)
    check  = div3(bits)
    assert truth == check

Ответ 12

Вот хорошая и быстрая реализация метода Ray Burns в C:

bool is_power_of_3(unsigned x) {
    if (x > 0x0000ffff)
        x *= 0xb0cd1d99;    // multiplicative inverse of 59049
    if (x > 0x000000ff)
        x *= 0xd2b3183b;    // multiplicative inverse of 243
    return x <= 243 && ((x * 0x71c5) & 0x5145) == 0x5145;
}

Он использует мультипликативный обратный трюк для первого деления на 3 ^ 10, а затем на 3 ^ 5. Наконец, необходимо проверить, есть ли результат 1, 3, 9, 27, 81 или 243, который выполняется с помощью некоторого простого хеширования, которое я обнаружил методом проб и ошибок.

На моем процессоре (Intel Sandy Bridge) это довольно быстро, но не так быстро, как метод starblue, который использует двоичный логарифм (который реализован в аппаратное обеспечение на этом ЦП). Но на процессоре без такой инструкции или когда таблицы поиска нежелательны, это может быть альтернативой.

Ответ 13

Это резюме всех хороших ответов ниже этих вопросов, а показатели производительности можно найти в статье LeetCode.

1. Итерация петли

Сложность времени O (log (n)), сложность пространства O (1)

public boolean isPowerOfThree(int n) {
    if (n < 1) {
        return false;
    }

    while (n % 3 == 0) {
        n /= 3;
    }

    return n == 1;
}

2. Базовое преобразование

Преобразуйте целое число в базовое число 3 и проверьте, записано ли оно как ведущее 1, за которым следуют все 0. Это вдохновляет решение проверить, имеет ли число значение 2, делая n & (n - 1) == 0

Сложность времени: O (log (n)) в зависимости от языка и компилятора, сложность пространства: O (log (n))

public boolean isPowerOfThree(int n) {
    return Integer.toString(n, 3).matches("^10*$");
}

3 Математика

Если n = 3^i, то i = log(n) / log(3) и, таким образом, приходит к решению

Сложность времени: в зависимости от языка и компилятора, сложность пространства: O (1)

public boolean isPowerOfThree(int n) {
    return (Math.log(n) / Math.log(3) + epsilon) % 1 <= 2 * epsilon;
}

4 Целочисленные ограничения

Поскольку 3^19 = 1162261467 - наибольшая степень 3-х чисел, подходит для 32-битного целого числа, поэтому мы можем сделать

Сложность времени: O (1), сложность пространства: O (1)

public boolean isPowerOfThree(int n) {
    return n > 0 && 1162261467 % n == 0;
}

5 Целочисленные ограничения с помощью Set

Идея похожа на # 4, но использует набор для хранения всей возможной мощности 3 чисел (от 3 ^ 0 до 3 ^ 19). Это делает код более удобочитаемым.

6 Рекурсивный (С++ 11)

Это решение специфично для С++ 11, используя мета-программирование шаблонов, чтобы complier заменил вызов isPowerOf3<Your Input>::cValue на вычисленный результат.

Сложность времени: O (1), сложность пространства: O (1)

template<int N>
struct isPowerOf3 {
    static const bool cValue = (N % 3 == 0) && isPowerOf3<N / 3>::cValue;
};

template<>
struct isPowerOf3<0> {
    static const bool cValue = false;
};

template<>
struct isPowerOf3<1> {
    static const bool cValue = true;
};

int main() {
    cout<<isPowerOf3<1162261467>::cValue;
    return 0;
}

Ответ 14

Вы можете сделать лучше, чем повторное деление, которое принимает время O (lg (X) * | div |). По существу, вы выполняете двоичный поиск по степеням 3. Действительно, мы будем выполнять двоичный поиск по N, где 3 ^ N = входное значение). Установка Pth двоичной цифры N соответствует умножению на 3 ^ (2 ^ P), а значения вида 3 ^ (2 ^ P) могут быть вычислены путем повторного квадратирования.

Алгоритм

  • Пусть входное значение будет X.
  • Создайте список L повторяющихся квадратов значений, которые заканчиваются после прохождения X.
  • Пусть ваше значение кандидата равно T, инициализировано 1.
  • Для каждого E в обратном L, если T * E <= X, то T * = E.
  • Возврат T == X.

Сложность:

O (lg (lg (X)) * | умножение |) - Генерация и итерация по L принимает итерации lg (lg (X)), а умножение - самая дорогая операция на итерации.

Ответ 15

Самое быстрое решение - либо тестирование, если n > 0 && 3**19 % n == 0, как указано в другом ответе, или отличное хэширование (ниже). Сначала я даю два решения на основе умножения.

Умножение

Интересно, почему все пропустили это умножение намного быстрее, чем деление:

for (int i=0, pow=1; i<=19, pow*=3; ++i) {
    if (pow >= n) {
        return pow == n;
    }
}
return false;

Просто попробуйте все силы, остановитесь, когда он станет слишком большим. Избегайте переполнения, поскольку 3**19 = 0x4546B3DB является самым большим подключением питания в подписанном 32-битном int.

Умножение с бинарным поиском

Двоичный поиск может выглядеть как

int pow = 1;
int next = pow * 6561; // 3**8
if (n >= next) pow = next;
next = pow * 81; // 3**4
if (n >= next) pow = next;
next = pow * 81; // 3**4; REPEATED
if (n >= next) pow = next;
next = pow * 9; // 3**2
if (n >= next) pow = next;
next = pow * 3; // 3**1
if (n >= next) pow = next;
return pow == next;

Один шаг повторяется, так что максимальный показатель 19 = 8+4+4+2+1 может быть достигнут точно.

Идеальное хеширование

В подписанный 32-битный int имеется 20 степеней из трех, поэтому мы берем таблицу из 32 элементов. При некоторых экспериментах я нашел идеальную хеш-функцию

def hash(x):
    return (x ^ (x>>1) ^ (x>>2)) & 31;

сопоставление каждой мощности с отдельным индексом между 0 и 31. Остальные вещи тривиальны:

// Create a table and fill it with some power of three.
table = [1 for i in range(32)]
// Fill the buckets.
for n in range(20): table[hash(3**n)] = 3**n;

Теперь мы имеем

table = [
     1162261467, 1, 3, 729, 14348907, 1, 1, 1,
     1, 1, 19683, 1, 2187, 81, 1594323, 9,
     27, 43046721, 129140163, 1, 1, 531441, 243, 59049,
     177147, 6561, 1, 4782969, 1, 1, 1, 387420489]

и может очень быстро протестировать через

def isPowerOfThree(x):
    return table[hash(x)] == x

Ответ 16

На ваш вопрос довольно легко ответить, указав простую функцию для запуска проверки. Пример реализации, показанный ниже, написан на Python, но не обязательно будет переписываться на других языках, если это необходимо. В отличие от последней версии этого ответа, код, показанный ниже, намного надежнее.

Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> import math
>>> def power_of(number, base):
    return number == base ** round(math.log(number, base))

>>> base = 3
>>> for power in range(21):
    number = base ** power
    print(f'{number} is '
          f'{"" if power_of(number, base) else "not "}'
          f'a power of {base}.')
    number += 1
    print(f'{number} is '
          f'{"" if power_of(number, base) else "not "}'
          f'a power of {base}.')
    print()


1 is a power of 3.
2 is not a power of 3.

3 is a power of 3.
4 is not a power of 3.

9 is a power of 3.
10 is not a power of 3.

27 is a power of 3.
28 is not a power of 3.

81 is a power of 3.
82 is not a power of 3.

243 is a power of 3.
244 is not a power of 3.

729 is a power of 3.
730 is not a power of 3.

2187 is a power of 3.
2188 is not a power of 3.

6561 is a power of 3.
6562 is not a power of 3.

19683 is a power of 3.
19684 is not a power of 3.

59049 is a power of 3.
59050 is not a power of 3.

177147 is a power of 3.
177148 is not a power of 3.

531441 is a power of 3.
531442 is not a power of 3.

1594323 is a power of 3.
1594324 is not a power of 3.

4782969 is a power of 3.
4782970 is not a power of 3.

14348907 is a power of 3.
14348908 is not a power of 3.

43046721 is a power of 3.
43046722 is not a power of 3.

129140163 is a power of 3.
129140164 is not a power of 3.

387420489 is a power of 3.
387420490 is not a power of 3.

1162261467 is a power of 3.
1162261468 is not a power of 3.

3486784401 is a power of 3.
3486784402 is not a power of 3.

>>> 

ПРИМЕЧАНИЕ.. Последняя ревизия заставила этот ответ стать почти таким же, как ответ TMS.

Ответ 17

Настроенное решение...

DECLARE @LastExponent smallint, @SearchCase decimal(38,0)

SELECT
    @LastExponent = 79, -- 38 for bigint
    @SearchCase = 729

;WITH CTE AS
(
    SELECT
        POWER(CAST(3 AS decimal(38,0)), ROW_NUMBER() OVER (ORDER BY c1.object_id)) AS Result,
        ROW_NUMBER() OVER (ORDER BY c1.object_id) AS Exponent
    FROM
        sys.columns c1, sys.columns c2
)
SELECT
    Result, Exponent
FROM
    CTE
WHERE
    Exponent <= @LastExponent
    AND
    Result = @SearchCase

С SET STATISTICS TIME ON он записывает минимально возможную 1 миллисекунду.

Ответ 18

Другой подход заключается в создании таблицы во время компиляции. Хорошо, что вы можете продлить это до 4, 5, 6, 7, независимо от того, что

template<std::size_t... Is>
struct seq
{  };

template<std::size_t N, std::size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>
{  };

template<std::size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>
{  };

template<std::size_t N>
struct PowersOfThreeTable
{
    std::size_t indexes[N];
    std::size_t values[N];

    static constexpr std::size_t size = N;
};

template<typename LambdaType, std::size_t... Is>
constexpr PowersOfThreeTable<sizeof...(Is)>
    generatePowersOfThreeTable(seq<Is...>, LambdaType evalFunc)
{
    return { {Is...}, {evalFunc(Is)...} };
}

template<std::size_t N, typename LambdaType>
constexpr PowersOfThreeTable<N> generatePowersOfThreeTable(LambdaType evalFunc)
{
    return generatePowersOfThreeTable(gen_seq<N>(), evalFunc);
}

template<std::size_t Base, std::size_t Exp>
struct Pow
{
    static constexpr std::size_t val = Base * Pow<Base, Exp-1ULL>::val;
};

template<std::size_t Base>
struct Pow<Base, 0ULL>
{
    static constexpr std::size_t val = 1ULL;
};

template<std::size_t Base>
struct Pow<Base, 1ULL>
{
    static constexpr std::size_t val = Base;
};

constexpr std::size_t tableFiller(std::size_t val)
{ 
    return Pow<3ULL, val>::val;
}

bool isPowerOfThree(std::size_t N)
{
    static constexpr unsigned tableSize = 41; //choosen by fair dice roll

    static constexpr PowersOfThreeTable<tableSize> table = 
            generatePowersOfThreeTable<tableSize>(tableFiller);

    for(auto a : table.values)
        if(a == N)
            return true;
    return false;
}

Ответ 19

Решение Python

from math import floor
from math import log

def IsPowerOf3(number):
  p = int(floor(log(number) / log(3)))
  power_floor = pow(3, p)
  power_ceil = power_floor * 3
  if power_floor == number or power_ceil == number:
    return True
  return False

Это намного быстрее, чем простое разделение на 3 решения.

Доказательство: 3 ^ p = число

p log (3) = log (число) (с учетом обеих сторон)

p = log (число)/log (3)

Ответ 20

Здесь общий алгоритм для определения, является ли число степенью другого числа:

bool IsPowerOf(int n,int b)
{
    if (n > 1)
    {
        while (n % b == 0)
        {
            n /= b;
        }
    }
    return n == 1;
}

Ответ 21

#include<iostream>
#include<string>
#include<cmath>
using namespace std;
int main()
{
     int n, power=0;
      cout<<"enter a number"<<endl;
      cin>>n;
  if (n>0){

     for(int i=0; i<=n; i++)
     {

         int r=n%3;

            n=n/3;
         if (r==0){
            power++;
         }

         else{
               cout<<"not exactly power of 3";
                return 0;

             }
     }

   }

         cout<<"the power is "<<power<<endl;
  }

Ответ 22

Это метод постоянного времени! Да. O (1). Для чисел фиксированной длины, скажем, 32 бит.

Учитывая, что нам нужно проверить, является ли целое число n степенью 3, начнем думать об этой проблеме с точки зрения того, какая информация уже имеется.

1162261467 - это наибольшая мощность 3, которая может вписываться в Java int.
1162261467 = 3^19 + 0

Данный n может быть выражен как [(степень 3) + (некоторая x)]. Я считаю, что достаточно элементарно доказать, что если x равно 0 (что происходит , если f n является степенью 3), 1162261467% n = 0.

Общая идея состоит в том, что если x - некоторая степень 3, x может быть выражена как Y/3a, где a - некоторое целое число, а X < Y. Это следует тем же самым принципом для Y < X. Случай Y = X является элементарным.

Итак, чтобы проверить, является ли заданное целое число n степенью трех, проверьте, если n > 0 && 1162261467 % n == 0.