É possível resolver isso de forma relativamente eficiente, computando todos os MDCs em pares, removendo duplicatas e recorrendo novamente. É o ato de remover duplicatas antes de você recursar que a torna eficiente.
Vou explicar o algoritmo com mais detalhes abaixo, mas primeiro, ele ajuda a definir um operador binário . Se são conjuntos de números inteiros positivos, defina⊗S,T
S⊗T={gcd(s,t):s∈S,t∈T}.
Observe quee (no seu problema); normalmente, será ainda menor do que qualquer um desses limites sugere, o que ajuda a tornar o algoritmo eficiente. Observe também que podemos calcular comoperações gcd por enumeração simples.|S⊗T|≤|S|×|T||S⊗T|≤109S⊗TS⊗T|S|×|T|
Com essa notação, aqui está o algoritmo. Seja o conjunto de números de entrada. Calcule , depois , depois e assim por diante. Encontre o menor tal que mas . Então você sabe que o tamanho do menor subconjunto é . Se você também deseja apresentar um exemplo concreto de um subconjunto, mantendo os ponteiros de retorno, é possível reconstruir facilmente esse conjunto.S1S2=S1⊗S1S3=S1⊗S2S4=S1⊗S3k1∈Sk1∉Sk−1k
Isso será relativamente eficiente, pois nenhum dos conjuntos intermediários aumenta em tamanho acima de (na verdade, seu tamanho provavelmente será muito menor que isso) e o tempo de execução requer cerca de operações gcd.109500×(|S1|+|S2|+⋯)
Aqui está uma otimização que pode melhorar ainda mais a eficiência. Basicamente, você pode usar a duplicação iterada para encontrar o menor tal que . Em particular, para cada elemento , acompanhamos o menor subconjunto de cujo gcd é e cujo tamanho é . (Ao remover duplicatas, você resolve laços em favor do subconjunto menor.) Agora, em vez de calcular a sequência de nove conjuntos , calculamos a sequência de cinco conjuntos , calculando , depois , em seguida,k1∈Skx∈SiS1x≤iS1,S2,S3,S4,…,S9S1,S2,S4,S8,S9S2=S1⊗S1S4=S2⊗S2S8=S4⊗S4 , então . À medida que avança, encontre o primeiro modo que . Depois de encontrar como , é possível parar imediatamente: você pode encontrar o menor subconjunto cujo gcd é observando o subconjunto associado a . Portanto, você pode parar assim que atingir um conjunto tal que , o que permite que você pare mais cedo se encontrar um subconjunto menor.S9=S1×S8k∈[1,2,4,8,9]1∈Skk1∈Sk11Sk1∈Sk
Isso deve ser eficiente em termos de tempo e espaço. Para economizar espaço, para cada elemento , você não precisa armazenar o conjunto inteiro: basta armazenar dois ponteiros traseiros (os dois elementos de quais você tirou o MDC, para obter ) e opcionalmente, o tamanho do subconjunto correspondente.x∈SkSi,Sjx
Em princípio, você pode substituir a sequência por qualquer outra cadeia de adição . Não sei se alguma outra cadeia de adição será melhor. A escolha ideal pode depender da distribuição de respostas corretas e dos tamanhos esperados dos conjuntos , o que não está claro para mim, mas provavelmente pode ser derivado empiricamente através da experimentação.[1,2,4,8,9]Sk
Créditos: Meus agradecimentos ao KWillets pela idéia de armazenar um subconjunto de números junto com cada elemento de , o que permite parar mais cedo.Si