Estou procurando um algoritmo eficiente para o problema:
Entrada : O número inteiro positivo (armazenado como bits) para algum número inteiro .
Saída : O número .
Pergunta : Podemos calcular partir dos bits de em tempo?
Esta é uma pergunta teórica motivada pela minha resposta a uma pergunta math.SE Como encontrar uma fórmula para esta bijeção? . Nesta questão, o autor queria encontrar uma bijeção de
Com a minha solução proposta, se sabemos que e m , podemos facilmente calcular 2 m ( 2 n + 1 ) (escrever os dígitos binários de n seguido por 1 seguido de m zeros). Isso leva tempo O ( n + m ) .
Encontrar partir dos bits de 2 m 3 n equivale a encontrar o bit menos significativo (que pode ser calculado contando as mudanças de bits corretas, deixando 3 n na memória). Isso leva tempo O ( m ) .
No entanto, também precisamos encontrar , o que pode ser mais difícil. Seria possível encontrar n dividindo repetidamente por 3 , mas isso parece um desperdício. Requer n operações de divisão, cada uma das quais levará tempo O ( n ) , portanto, esse é o tempo O ( n 2 ) no total. [Na verdade, após cada iteração, o número de dígitos diminui linearmente, mas isso ainda resulta em tempo de O ( n 2 ) .]
Parece que deveríamos ser capazes de explorar sabendo que a entrada é uma potência de .
fonte
Respostas:
A abordagem óbvia é:
(1) Calcule uma aproximação para o . Você pode aproximá-lo para dentro de um erro aditivo de 1 contando o número de bits na representação binária fornecida e para dentro de um erro aditivo de ϵ olhando adicionalmente para o O superior ( log 1log2(3n) ϵ bits de entrada. Ele deve ser suficiente para escolher um valor constante deε, de modo que (após combinação com o erro no passo (2)) das extremidades finais de resultados acima dentro de um erro aditivo de1/2da correcta.O(log1ϵ) ϵ 1/2
(2) Calcule uma aproximação ao . Não estou familiarizado com os algoritmos para isso, mas espero que eles levem tempo polinomial no número de bits de precisão que você precisa, e você só precisa de O ( log n ) bits de precisão.log2(3) O(logn)
(3) Divida a resposta em (1) pela resposta em (2) e arredonde para o número inteiro mais próximo.
Portanto, o primeiro passo leva tempo linear (na maioria dos modelos de computação, embora talvez não seja o caso de alguns com pouca potência, como as máquinas de Turing de cabeça única ) e os demais passos devem ser polilogarítmicos.
fonte
fonte
Portanto, usando o log discreto e o levantamento de Hensel, acho que você deve poder calcular partir dos dígitos baixos de muita eficiência. Em outras palavras, você começa calculando partir do dígito baixo de , levando o log discreto de para a base , módulo ; isso revela o e pode ser feito no tempo . Então, você encontra o log discreto de para a base , módulo ; isso revela o e pode ser feito emnmodφ(5k) k 3n nmod4 3n 3nmod5 3 5 nmod4 O(1) 3nmod25 e 25 nmod20 O(1) time (aproveitando o conhecimento do , existem apenas possibilidades que você precisa tentar). Iterar. Em cada etapa, você usa o conhecimento de para ajudá-lo a calcular com eficiência o log discreto de , aproveitando o fato de que existem apenas valores possíveis para .nmod4 5 nmodφ(5k−1) 3nmod5k 5 nmodφ(5k)
Agora apenas deixe ser grande o suficiente, e isso revela .k n
Você precisará descobrir se o tempo de execução é , mas me parece que pode ser. Suspeito que seja suficiente deixar e suspeito que você possa fazer cada iteração em tempo, para um total de tempo.O(n) k=O(n) O(1) O(n)
fonte