Acho que o propósito desse problema e ‘pegar’ os iniciantes. Ele parece ser bem inocente mas, na verdade, não é. Se você não usar uma técnica chamada parecida com outra chamada Memoization, ele não passa (passar passa, mas é difícil). Essa técnica de Memoization é bem simples: memorize o que você já fez. Por exemplo, pra calcular o fatorial de 2, o computador resolve bem rápido. 2 * 1 = 2. De 3, também: 3 * 2 * 1. De 10, já parece demorar um pouco mais. Agora imagine de 10000. Demora bastante se você não usar Memoization.
Nesses problemas eles geralmente dizem o maior valor que será entrado De posse disso, você pode criar uma estrutura de dados pra armazenar o resultado dos valores já entrado, não precisando ‘percorrer todo o caminho’. Ainda, no fatorial, se pedissem pra calcular o fatorial de um número gigantesco depois de calcular o fatorial de diversos outros números menores, você pode tirar vantagem disso.
Supondo que n seja a entrada, e 100 (cem) seja o maior valor entrado (geralmente é muito maior, mas dependendo da quantidade de dígitos do resultado você deve usar outras técnicas, como Big Num, mas isso é mais tarde). Você pode criar um vetor de Long (em Java) ou long long em C++. Long porque int não consegue ‘aguentar’ o tranco, ou seja, não consegue suportar a quantidade de dígitos do resultado (alguns chegam a 10, 15 dígitos).
Certo. Criamos o vetor de Long. E agora? Agora, inicializamos as duas primeiras posições dele:
vetor[0] = 1;
vetor[1] = 1;
Agora, basta armazenar o resultado das entradas:
Entrou 2.
vetor[2] = 2 * vetor[1];
vetor[2] = 2;
Entrou 3.
vetor[3] = 3 * vetor[2];
vetor[3] = 6;
Entrou 5:
se vetor[4] for nulo (ou nil, ou 0), pegamos o vetor[3] e fazemos o mesmo procedimento.
Pra entradas pequenas parece ser muito inútil. Mas imagine que você tenha calculado o fatorial de 10 e seja pedido o de 11. Em vez de você fazer 11!, você faz 11 * fatorial de 10. Isso dá MUITA diferença no tempo com que o resultado final é impresso. Acho que mais confundi que expliquei
Tem muito desse tipo de problema. Quando é simples, como o 3n + 1 ou esse do fatorial, é tranquilo de ver que é necessário usar uma estrutura pra memorizar os resultados.
Acho que eu tenho esse problema resolvido (não veja se quiser tentar por si próprio, que é o melhor) num repositório pra códigos no Google Code criado pela minha pessoa. A proposta do repositório era manter a nossa equipe da maratona de programação atualizada, mas ninguém se interessou. Se você andar mais pra trás nos diretórios vai ver que tem alguns problemas resolvidos no SPOJ (na verdade, tem bem pouco no uva). Hoje em dia ando meio sem tempo de resolver, mas quando puder coloco alguns novos lá.
Aliás, outro forum ótimo pra comentar sobre esses problemas é o do spoj. Tem o do uva e o do spoj polonês (que é tudo em inglês) também.
Sobre usar Java, nunca consegui resolver um direito :\ Tanto que aprendi o que sei de C++ pra usar na maratona (e é bem pouca coisa).
Abraço.