def combination_sum(candidates, target):
    values = sorted(set(candidates))
    output, path = [], []
    def visit(start, remaining):
        if remaining == 0:
            output.append(path.copy())
            return
        for i in range(start, len(values)):
            value = values[i]
            if value > remaining:
                break
            path.append(value)
            visit(i, remaining - value)
            path.pop()
    visit(0, target)
    return output
