Fazer um programa em C que leia um número e imprima se ele é ou não um número triangular. Um número triangular é aquele que é o produto de três números consecutivos. Por exemplo:
* 3 * 4 .
Passo 1
O enunciado pede que eu faça um programa em C que:
- Leia um número (entrada).
- Imprima se esse número é ou não um número triangular, onde um número triangular aqui é definido como o produto de três números inteiros consecutivos (por exemplo,
).
Informações relevantes dadas:
- Exemplo:
. - Resultado esperado: uma mensagem indicando se o número lido é triangular ou não.
Assunções que vou adotar (porque o enunciado não especificou detalhes de entrada/saída):
- A entrada será um número inteiro não-negativo que caiba em um tipo inteiro com sinal largo (vou usar
unsigned long longpara cobrir números grandes). - Para a interpretação do problema consideramos triângulos formados por três inteiros consecutivos
com . (Observação: existe produto de três consecutivos negativos que dá negativos, mas o exemplo e o uso típico consideram números não-negativos.)
Passo 2
Entendendo a propriedade matemática que vamos testar:
- Queremos verificar se existe um inteiro
tal que
- Se encontrarmos esse
, então é triangular; caso contrário, não é.
Explicação didática dessa equação:
- A expressão
é um polinômio cúbico em . - Para
essa função cresce com (é estritamente monótona crescente para ), então ao testar em ordem crescente, assim que o produto ultrapassar podemos parar — não há necessidade de testar valores maiores.
Passo 3
Escolha do método de resolução (por que não tentar resolver a equação simbolicamente?):
- Poderíamos tentar resolver a equação cúbica para
, mas isso envolve raízes e arredondamentos, e é desnecessariamente complicado para um programa de prova. - Método escolhido: busca direta (iterativa) em
calculando até que (sucesso) ou (fracasso). Esse método é simples, robusto e fácil de implementar sem depender de bibliotecas extras. - Complexidade: se
, então , logo o laço tem cerca de iterações — perfeitamente aceitável para tamanhos razoáveis de .
Passo 4
Problema prático importante: evitar overflow ao multiplicar
- Em C, ao calcular
pode ocorrer overflow se os valores forem grandes. - Estratégia segura:
- Antes de efetuar uma multiplicação que pode estourar, usar divisões para checar se a multiplicação seria maior que
. Ex.: para saber se sem multiplicar, verificar se e . Se isso for verdade, então e, portanto, — podemos parar. - Só efetuar a multiplicação quando tivermos certeza de que o resultado cabe e não ultrapassa
.
- Antes de efetuar uma multiplicação que pode estourar, usar divisões para checar se a multiplicação seria maior que
- Assim garantimos que nunca multiplicamos dois números grandes que causariam wrap-around silencioso e resultado incorreto.
Passo 5
Descrição passo a passo do algoritmo que vamos implementar em C:
- Ler
(tipo unsigned long long). - Para
: - Verificar se
usando divisão segura; se for, parar (não é triangular). - Calcular
(aqui é seguro porque garantimos ). - Verificar se
usando divisão segura; se for, parar (não é triangular). - Calcular
. - Se
, então é triangular — sucesso. - Se
, parar (não é triangular).
- Verificar se
- Se nenhuma iteração encontrou igualdade, imprimir que não é triangular.
Observações de implementação:
- Começamos em
porque e é um caso válido (se a entrada for devolveremos que é triangular). - Usamos condições com divisão inteira para garantir segurança contra overflow antes de multiplicar.
Passo 6
Como traduzir isso para C (detalhes práticos de leitura e saída):
- Leitura: usar
scanf("%llu", &n)paraunsigned long long n. - Saída: imprimir uma frase clara em português, por exemplo:
- Se for triangular: “O numero
e triangular.\n” - Se não for: “O numero
nao e triangular.\n”
- Se for triangular: “O numero
- Eu sei que você pode preferir saída curta (SIM/NAO). Se você precisar de formato específico para um juiz automático, adapte as mensagens. Aqui eu deixo mensagens descritivas para facilitar entendimento na prova manual.
Passo 7
Exemplo de execução mental com
(isso serve de “aula prática”):
-
: . -
: . -
: -> achamos , então o programa imprime que é triangular.
Isso ilustra bem a busca incremental: paramos nocerto.
Passo 8
Casos especiais e dicas para prova:
- Entrada
: nossa implementação retorna “triangular” (porque ). - Entrada pequena como
: não triangular (nenhum produto de três consecutivos dá esses valores). - Se o enunciado exigir aceitar negativos ou considerar produtos de três consecutivos negativos, o código precisa ser adaptado — aqui assumimos
. Se quiser, posso depois mostrar a versão que aceita inteiros negativos (procura negativo também). - Sempre explique no enunciado da prova qual convenção você está usando (por exemplo, “assumo
inteiro não-negativo”).
Passo 9
Código completo em C (implementação segura contra overflow e com saída em português).
- O código abaixo implementa exatamente o algoritmo descrito e usa verificações por divisão antes de multiplicar para evitar overflow silencioso.
Resposta
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
int main(void) {
unsigned long long n;
if (scanf("%llu", &n) != 1) return 0;
unsigned long long n;
if (scanf("%llu", &n) != 1) return 0;
int found = 0;
for (unsigned long long k = 0;; ++k) {
/* Antes de calcular a = k*(k+1), verificamos se k*(k+1) > n sem multiplicar */
if (k != 0 && n / k < (k + 1)) break; /* então k*(k+1) > n -> produto final > n */
unsigned long long a = k * (k + 1); /* seguro pois a <= n */
/* Antes de calcular p = a*(k+2), verificamos se a*(k+2) > n sem multiplicar */
if (a != 0 && n / a < (k + 2)) break; /* então a*(k+2) > n -> produto final > n */
unsigned long long p = a * (k + 2); /* seguro */
if (p == n) { found = 1; break; }
if (p > n) break;
/* caso p < n, continua com próximo k */
}
if (found)
printf("O numero %llu e triangular.\n", n);
else
printf("O numero %llu nao e triangular.\n", n);
return 0;
}