En effet, il existe un algorithme de temps linéaire pour cela. Il vous suffit d'utiliser certains concepts de base de la théorie des nombres. Étant donné deux numéros et , leur somme est divisible à , que si la somme de leur reste est divisible à . En d'autres termes,n1n2KK
K∣(n1+n2) ⟺ K∣((n1 mod K)+(n2 mod K)).
Le deuxième concept que vous devez considérer est que la somme de deux nombres est , uniquement si l'un d'eux est strictement inférieur à et l'autre n'est pas inférieur à . En d'autres termes,r1≠r2KK/2K/2
r1+r2=K ⇒ r1<K/2, r2≥K/2 (r1≠r2, w.l.g. r1<r2).
Le troisième concept que vous devez considérer est que, si la somme de deux nombres est , ils s'écartent tous les deux de d'un certain , c'est à dire,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.
Donc, pour evey dans le troisième concept, vous devez mettre ou dans l'ensemble de solutions, mais pas les deux. Vous êtes autorisé à mettre l'un des nombres qui sont réellement divisibles par et si est pair, vous ne pouvez ajouter qu'un seul nombre dont le reste est .kr1r2KKK/2
Voici donc l'algorithme.
Étant donné un ensemble , trouvons l'ensemble de solutionN={n1,n2,⋯,nN}S,
- ConsidéronsR={r1=(n1 mod K),r2=(n2 mod K),⋯,rN=(nN mod K)}
- S←∅
- pour à :k←1⌈K/2⌉−1
- si :count(R,k)≥count(R,K−k)
- ajoutez tous les à , de telle sorte queniSri=k
- sinon:
- ajoutez tous les à , de telle sorte queniSri=K−k
- ajouter un seul à telle sorte que // s'il existeniSri=0
- si est pair:K
- ajoutez un seul à telle sorte que // s'il existeniSri=K/2
- SortieS
L'algorithme est assez long, mais l'idée est très simple.