jacknpoe

cálculo de Máximo Divisor Comum (MDC) e Mínimo Múltiplo Comum (MMC)

Apr 18th, 2026 (edited)
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.35 KB | Software | 0 0
  1. // Fatoração e Cálculo de Máximo Divisor Comum (MDC) e Mínimo Múltiplo Comum (MMC)
  2. // VERSÕES: 0.1: 18/04/2026: versão testada com sucesso com vários valores
  3. //          0.2: 19/04/2026: otimizações de todos os tipos, envolvendo CharGPT,
  4. //                           principalmente passando de array para vector, nisso excluindo Ultimo e Maximo
  5. //          0.3: 20/04/2026: retirada a necessidade de avaliar raiz de produto, tirado getExpemte() Primo e math.h
  6. //                           argumentos para número de testes, melhorias pelo ChatGPT
  7.  
  8. // ATENÇÃO
  9. // embora os tempos fiquem melhores com a opção de otimização -O3 ao compilar,
  10. // ela não faz as chamadas a setProduto(), mdc() e mmc() dentro das medições
  11. // de tempo, o que causa valores próximos ou iguais a zero
  12. // ATUALIZAÇÃO
  13. // volatile int64_t mdc, mmc, qtdeFatores parece ter resolvido o problema de compilar com -O3
  14.  
  15. #include <cstdint>  // int64_t
  16. #include <iostream> // cout, endl
  17. #include <cstdlib>  // calloc, free
  18. #include <algorithm>  // min, max
  19. #include <chrono>  // now(), time_point, milisecond
  20. #include <vector>  // vetores
  21.  
  22. using namespace std;
  23.  
  24. // função de expomnencial de inteiros (para uso no domínio do problema, base >= 0, expoente >= 0)
  25. int64_t powint(int64_t base, int64_t exp) {
  26.     int64_t r = 1;
  27.     while (exp > 0) {
  28.         if (exp & 1) r *= base;
  29.         base *= base;
  30.         exp >>= 1;
  31.     }
  32.     return r;
  33. }
  34.  
  35. // #include <cstdint>
  36. // #include <cstdlib>
  37.  
  38. // using namespace std;
  39.  
  40. // using u64 = uint64_t;
  41. // using u128 = __uint128_t;
  42.  
  43. // // ------------------------------
  44. // // MDC (algoritmo de Euclides)
  45. // // ------------------------------
  46. // u64 mdc(u64 a, u64 b) {
  47. //     while (b != 0) {
  48. //         u64 r = a % b;
  49. //         a = b;
  50. //         b = r;
  51. //     }
  52. //     return a;
  53. // }
  54.  
  55. // // ------------------------------
  56. // // MMC seguro (evita overflow intermediário)
  57. // // ------------------------------
  58. // u64 mmc(u64 a, u64 b) {
  59. //     u64 g = mdc(a, b);
  60. //     // (a / g) * b evita overflow mais cedo
  61. //     return (u128)(a / g) * b;
  62. // }
  63.  
  64. // classe que encontra os fatores de um Produto e com as funções estáticas mdc e mmc
  65. class Fatoracao{
  66.     private:
  67.         int64_t Produto;
  68.         vector<std::pair<int64_t, int64_t>> VExpoentes;
  69.     public:
  70.         Fatoracao(int64_t produto);
  71.         Fatoracao(void);
  72.         bool setProduto(int64_t produto);
  73.         inline int64_t getProduto(void) const ;
  74.         inline bool getPrimo(void) const ;
  75.         inline size_t getQuantidadeFatores() const ;
  76.         inline int64_t getFatorPorIndice(size_t i) const ;
  77.         inline int64_t getExpoentePorIndice(size_t i) const ;
  78.         static int64_t mdc(const Fatoracao& num1, const Fatoracao& num2);
  79.         static int64_t mmc(const Fatoracao& num1, const Fatoracao& num2);
  80.         Fatoracao(const Fatoracao&) = delete;
  81.         Fatoracao& operator=(const Fatoracao&) = delete;
  82. };
  83.  
  84. // muda o valor do produto, preenche os atributos, principalmente VExpoentes, que são fatores indexados
  85. // caso retorne false, não usar o objeto, pois irá se comportar como se tivesse o valor 1
  86. bool Fatoracao::setProduto(int64_t produto) {
  87.     Produto = produto;
  88.  
  89.     // limpa VExpoentes para poder reutilizar o mesmo objeto para várias fatorações
  90.     VExpoentes.clear();
  91.  
  92.     // se produto == 1, não preenche VExpoentes
  93.     // se produto < 1, equivalente a 1, com a diferença que setProduto retorna falso (erro)
  94.     if(produto < 2) {
  95.         return produto == 1;
  96.     }
  97.  
  98.     // encontra e guarda os expoentes para os números em VExpoentes
  99.     int64_t indice = 3, atual = 0;
  100.  
  101.     // primeiro, o fator 2
  102.     while(produto % 2 == 0) {
  103.         if(atual == 2) VExpoentes.back().second++;
  104.         else { VExpoentes.push_back({2, 1}); atual = 2; }
  105.  
  106.         produto /= 2;
  107.     }
  108.    
  109.     // depois, os fatores ímpares
  110.     while(indice * indice <= produto) {
  111.         if(produto % indice == 0) {
  112.             if(indice == atual) VExpoentes.back().second++;
  113.             else { VExpoentes.push_back({indice, 1}); atual = indice; }
  114.  
  115.             produto /= indice;
  116.         } else {
  117.             indice += 2;
  118.         }
  119.     }
  120.  
  121.     // o produto que sobra
  122.     if(produto > 1) { if(produto == atual) VExpoentes.back().second++;
  123.                       else VExpoentes.push_back({produto, 1}); }
  124.  
  125.     return true;
  126. }
  127.  
  128. // retorna o número fatorado original, inválido se setProduto retornou false
  129. inline int64_t Fatoracao::getProduto(void) const { return Produto; }
  130.  
  131. // retorna a quantidade de fatores
  132. inline size_t Fatoracao::getQuantidadeFatores() const { return VExpoentes.size(); }
  133.  
  134. // retorna qual é o fator do elemento indice do vetor de fatores
  135. inline int64_t Fatoracao::getFatorPorIndice(size_t indice) const { return (indice < VExpoentes.size()) ? VExpoentes[indice].first : 0; }
  136.  
  137. // retorna qual é o expoente do elemento indice do vetor de fatores
  138. inline int64_t Fatoracao::getExpoentePorIndice(size_t indice) const { return (indice < VExpoentes.size()) ? VExpoentes[indice].second : 0; }
  139.  
  140. // retorna o Máximo Divisor Comum (MDC) entre dois números fatorados
  141. int64_t Fatoracao::mdc(const Fatoracao& num1, const Fatoracao& num2) {
  142.     int64_t produto = 1, indice1 = 0, indice2 = 0, multiplicador;
  143.     size_t qtdFatores1 = num1.getQuantidadeFatores(); size_t qtdFatores2 = num2.getQuantidadeFatores();
  144.     int64_t fator1 = num1.getFatorPorIndice(0); int64_t fator2 = num2.getFatorPorIndice(0);
  145.    
  146.     while(true) {
  147.         if(indice1 == qtdFatores1 || indice2 == qtdFatores2) break;
  148.  
  149.         if(fator2 > fator1) {
  150.             indice1++;
  151.             if(indice1 < qtdFatores1) fator1 = num1.getFatorPorIndice(indice1);
  152.             continue;
  153.         }
  154.  
  155.         if(fator1 > fator2) {
  156.             indice2++;
  157.             if(indice2 < qtdFatores2) fator2 = num2.getFatorPorIndice(indice2);
  158.             continue;
  159.         }
  160.  
  161.         multiplicador = powint(fator1, min(num1.getExpoentePorIndice(indice1), num2.getExpoentePorIndice(indice2)));
  162.         if(produto > INT64_MAX / multiplicador) return 0;
  163.         produto *= multiplicador;
  164.  
  165.         indice1++;
  166.         if(indice1 < qtdFatores1) fator1 = num1.getFatorPorIndice(indice1);
  167.         indice2++;
  168.         if(indice2 < qtdFatores2) fator2 = num2.getFatorPorIndice(indice2);
  169.     }
  170.     return produto;
  171. }
  172.  
  173. // retorna o Mínimo Múltiplo Comum (MMC) entre dois números fatorados
  174. int64_t Fatoracao::mmc(const Fatoracao& num1, const Fatoracao& num2) {
  175.     int64_t produto = 1, indice1 = 0, indice2 = 0, multiplicador;
  176.     size_t qtdFatores1 = num1.getQuantidadeFatores(); size_t qtdFatores2 = num2.getQuantidadeFatores();
  177.     int64_t fator1 = num1.getFatorPorIndice(0); int64_t fator2 = num2.getFatorPorIndice(0);
  178.    
  179.     while(true) {
  180.         if(indice1 == qtdFatores1 && indice2 == qtdFatores2) break;
  181.  
  182.         if(indice1 < qtdFatores1 && (indice2 == qtdFatores2 || fator2 > fator1)) {
  183.             multiplicador = powint(fator1, num1.getExpoentePorIndice(indice1));
  184.             if(produto > INT64_MAX / multiplicador) return 0;
  185.             produto *= multiplicador;
  186.  
  187.             indice1++;
  188.             if(indice1 < qtdFatores1) fator1 = num1.getFatorPorIndice(indice1);
  189.             continue;
  190.         }
  191.  
  192.         if(indice2 < qtdFatores2 && (indice1 == qtdFatores1 || fator1 > fator2)) {
  193.             multiplicador = powint(fator2, num2.getExpoentePorIndice(indice2));
  194.             if(produto > INT64_MAX / multiplicador) return 0;
  195.             produto *= multiplicador;
  196.  
  197.             indice2++;
  198.             if(indice2 < qtdFatores2) fator2 = num2.getFatorPorIndice(indice2);
  199.             continue;
  200.         }
  201.  
  202.         multiplicador = powint(fator1,max(num1.getExpoentePorIndice(indice1), num2.getExpoentePorIndice(indice2)));
  203.         if(produto > INT64_MAX / multiplicador) return 0;
  204.         produto *= multiplicador;
  205.  
  206.         indice1++;
  207.         if(indice1 < qtdFatores1) fator1 = num1.getFatorPorIndice(indice1);
  208.         indice2++;
  209.         if(indice2 < qtdFatores2) fator2 = num2.getFatorPorIndice(indice2);
  210.     }
  211.     return produto;
  212. }
  213.  
  214. // construtor que recebe um valor para o produto fatorado e delega o fatoramento para SetProduto()
  215. Fatoracao::Fatoracao(int64_t produto) {
  216.     setProduto(produto);
  217. }
  218.  
  219. // construtor que não recebe valor para o produto fatorado e preenche os atributos com valores zerados
  220. Fatoracao::Fatoracao(void) {
  221.     Produto = 0;
  222. }
  223.  
  224. // imprime os fatores de um produto num1, de número numero
  225. void imprimeFatores(const Fatoracao& fat, int numero) {
  226.     // imprime o fatoramento do número
  227.     cout << endl << "NÚMERO " << numero << ":" << endl;
  228.  
  229.     size_t quantidade = fat.getQuantidadeFatores();
  230.     for(size_t indice = 0; indice < quantidade; indice++)
  231.         cout << "Fator " << fat.getFatorPorIndice(indice) << " vezes " << fat.getExpoentePorIndice(indice) << endl;
  232. }
  233.  
  234. // testes
  235. int main(int argc, char* argv[]) {
  236.     Fatoracao num1, num2; long xFatorar = 1000, xMdcMmc = 1000;
  237.     int64_t val1, val2; volatile int64_t mdc, mmc, qtdeFatores = 0;
  238.  
  239.     chrono::steady_clock::time_point inicio, fim;
  240.     chrono::milliseconds duracao;
  241.  
  242.     if(argc > 1) xFatorar = strtol(argv[1], nullptr, 10);
  243.     if(argc > 2) xMdcMmc = strtol(argv[2], nullptr, 10);
  244.  
  245.     while(true) {
  246.  
  247.         // pede o primeiro número, validando usando setProduto como avaliador de sucesso
  248.         while(true) {
  249.             cout << "Número 1: ";
  250.             cin >> val1;
  251.             if(val1 == 0) exit(0);
  252.             if(num1.setProduto(val1)) break;
  253.             cout << "Número muito pequeno ou muito grande!" << endl;
  254.         }
  255.  
  256.  
  257.         // pede o segundo número, validando usando setProduto como avaliador de sucesso
  258.         while(true) {
  259.             cout << "Número 2: ";
  260.             cin >> val2;
  261.             if(val2 == 0) exit (0);
  262.             if(num2.setProduto(val2)) break;
  263.             cout << "Número muito pequeno ou muito grande!" << endl;
  264.         }
  265.  
  266.  
  267.         // imprime os fatoramentos dos números
  268.         imprimeFatores(num1, 1);
  269.         imprimeFatores(num2, 2);
  270.  
  271.         cout << endl;
  272.  
  273.  
  274.         // imprime o Máximo Divisor Comum (MDC)
  275.         mdc = Fatoracao::mdc(num1, num2);
  276.         cout << "MDC = " << mdc << endl;
  277.  
  278.         // imprime o Mínimo Múltiplo Comum (MMC)
  279.         mmc = Fatoracao::mmc(num1, num2);
  280.         cout << "MMC = " << mmc << endl << endl;
  281.  
  282.  
  283.         // mede o tempo de fatorar num1 e num2 1000 vezes
  284.         inicio = chrono::steady_clock::now();
  285.         for(long indice = 0; indice < xFatorar; indice++) {
  286.             num1.setProduto(val1);
  287.             num2.setProduto(val2);
  288.             qtdeFatores += num1.getQuantidadeFatores() + num2.getQuantidadeFatores();
  289.         }
  290.         fim = chrono::steady_clock::now();
  291.  
  292.         duracao = chrono::duration_cast<chrono::milliseconds>(fim - inicio);
  293.         cout << "Tempo decorrido fatoração (num1, num2) (" << xFatorar << " vezes): " << duracao.count() << " ms" << endl << endl;
  294.  
  295.  
  296.         // mede o tempo de calcular MDC + MMC 1000 vezes
  297.         inicio = chrono::steady_clock::now();
  298.         for(long indice = 0; indice < xMdcMmc; indice++) {
  299.             mdc = Fatoracao::mdc(num1, num2);
  300.             mmc = Fatoracao::mmc(num1, num2);
  301.         }
  302.         fim = chrono::steady_clock::now();
  303.  
  304.         duracao = chrono::duration_cast<chrono::milliseconds>(fim - inicio);
  305.         cout << "Tempo decorrido MDC + MMC (" << xMdcMmc << " vezes): " << duracao.count() << " ms" << endl << endl;
  306.     }
  307. }
  308.  
  309.  
Tags: GCD MMC MDC lcm
Add Comment
Please, Sign In to add comment