De fato, existe um algoritmo de tempo linear para isso. Você só precisa usar alguns conceitos básicos da teoria dos números. Dados dois números e , sua soma é divisível para , somente se a soma de sua restante é divisível para . Em outras palavras,n1n2KK
K∣(n1+n2) ⟺ K∣((n1 mod K)+(n2 mod K)).
O segundo conceito que você precisa considerar é que, a soma de dois números é , apenas se um deles for estritamente menor que e o outro não for menor que . Em outras palavras,r1≠r2KK/2K/2
r1+r2=K ⇒ r1<K/2, r2≥K/2 (r1≠r2, w.l.g. r1<r2).
O terceiro conceito que você precisa considerar é que, se a soma dos dois números for , ambos se desviarão de por um certo , ou seja,r1≠r2K⌈K/2⌉−1k≤⌈K/2⌉
r1+r2=K ⇒ ∃k≤⌈K/2⌉−1 such that r1=⌈K/2⌉−1−k, r2=⌈K/2⌉+k.
Portanto, para evey no terceiro conceito, você precisa colocar ou no conjunto de soluções, mas não os dois. Você pode colocar um dos números que são realmente divisíveis por e, se for par, você poderá adicionar apenas um número cujo restante seja .kr1r2KKK/2
Portanto, aqui está o algoritmo.
Dado um conjunto , vamos encontrar o conjunto de soluçõesN={n1,n2,⋯,nN}S,
- ConsidereR={r1=(n1 mod K),r2=(n2 mod K),⋯,rN=(nN mod K)}
- S←∅
- para no :k←1⌈K/2⌉−1
- se :count(R,k)≥count(R,K−k)
- adiciona todos os a , de modo queniSri=k
- else:
- adiciona todos os a , de modo queniSri=K−k
- adicione apenas um a , para que // se existirniSri=0
- se é par:K
- adicione apenas um a modo que // se existirniSri=K/2
- SaídaS
O algoritmo é bastante longo, mas a ideia é muito simples.