Самым быстрым решением является либо проверка, если 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
может быть точно достигнут.
Идеальное хеширование
Есть 20 степеней трех, вписывающихся в 32-битное целое со знаком, поэтому мы возьмем таблицу из 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