Đặt hàng tổng hợp con


22

Một tập hợp các nsố dương có 2^ntập con. Chúng tôi sẽ gọi một tập hợp "tốt đẹp" nếu không có tập hợp con nào có cùng một tổng. {2, 4, 5, 8}là một trong những bộ đẹp như vậy. Vì không có tập con nào có cùng một tổng, nên chúng ta có thể sắp xếp các tập con theo tổng:

[{}, {2}, {4}, {5}, {2, 4}, {2, 5}, {8}, {4, 5}, {2, 8}, {2, 4, 5}, {4, 8}, {5, 8}, {2, 4, 8}, {2, 5, 8}, {4, 5, 8}, {2, 4, 5, 8}]

Nếu chúng ta gắn nhãn các số [2, 4, 5, 8]với các ký hiệu [a, b, c, d]theo thứ tự tăng dần, chúng ta sẽ nhận được thứ tự trừu tượng sau:

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}]

Một tập hợp tốt đẹp khác của các số dương có thể có cùng thứ tự trừu tượng hoặc một số khác. Ví dụ, [3, 4, 8, 10]là một bộ đẹp với một thứ tự trừu tượng khác nhau:

[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}]

Trong thử thách này, bạn phải đếm số thứ tự trừu tượng riêng biệt của các bộ số ndương đẹp . Chuỗi này là OEIS A009997 và các giá trị đã biết, bắt đầu từ n=1, là:

1, 1, 2, 14, 516, 124187, 214580603

Ví dụ, n=3sau đây là hai thứ tự trừu tượng có thể có:

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}]
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {a, b, c}]

Đối với n=4, sau đây là 14 thứ tự trừu tượng có thể, cộng với một ví dụ đẹp được đặt với thứ tự đó:

[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {a, b, c}, {d}, {a, d}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 4, 2, 1]                                       
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {b, c}, {d}, {a, b, c}, {a, d}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 6, 3, 2]                                      
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 7, 4, 2]                                      
[{}, {a}, {b}, {a, b}, {c}, {a, c}, {d}, {a, d}, {b, c}, {a, b, c}, {b, d}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 4, 1]                                       
[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 8, 4, 3]                                      
[{}, {a}, {b}, {a, b}, {c}, {d}, {a, c}, {a, d}, {b, c}, {b, d}, {a, b, c}, {a, b, d}, {c, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 7, 4, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}, {d}, {a, d}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 4, 3, 2]                                      
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {d}, {a, b, c}, {a, d}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 4, 3, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {b, c}, {a, d}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 5, 4, 2]                                       
[{}, {a}, {b}, {c}, {a, b}, {a, c}, {d}, {a, d}, {b, c}, {a, b, c}, {b, d}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 7, 6, 2]                                      
[{}, {a}, {b}, {c}, {a, b}, {d}, {a, c}, {b, c}, {a, d}, {b, d}, {a, b, c}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 4, 3]                                       
[{}, {a}, {b}, {c}, {a, b}, {d}, {a, c}, {a, d}, {b, c}, {b, d}, {a, b, c}, {c, d}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [10, 8, 6, 3]                                      
[{}, {a}, {b}, {c}, {d}, {a, b}, {a, c}, {b, c}, {a, d}, {b, d}, {c, d}, {a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [8, 6, 5, 4]                                       
[{}, {a}, {b}, {c}, {d}, {a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d}, {a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}, {a, b, c, d}], [7, 6, 5, 3]

Sau đây không phải là một thứ tự trừu tượng hợp lệ:

{}, {a}, {b}, {c}, {d}, {a,b}, {e}, {a,c}, {b,c}, {a,d}, {a,e}, {b,d}, {b,e}, {c,d}, {a,b,c}, {a,b,d}, {c,e}, {d,e}, {a,b,e}, {a,c,d}, {a,c,e}, {b,c,d}, {b,c,e}, {a,d,e}, {b,d,e}, {a,b,c,d}, {c,d,e}, {a,b,c,e}, {a,b,d,e}, {a,c,d,e}, {b,c,d,e}, {a,b,c,d,e}

Thứ tự này ngụ ý rằng:

d < a + b
b + c < a + d
a + e < b + d
a + b + d < c + e

Tổng hợp các bất đẳng thức này cho:

2a + 2b + c + 2d + e < 2a + 2b + c + 2d + e

đó là một mâu thuẫn. Mã của bạn không được tính thứ tự này. Counterexamples như vậy đầu tiên xuất hiện tại n=5. Ví dụ từ bài báo này , ví dụ 2.5 trên trang 3.

Lệnh này không hợp lệ mặc dù thực tế A < Bngụ ý rằng A U C < B U C, đối với bất kỳ sự Crời rạc nào từ AB.


Mã hoặc chương trình của bạn phải đủ nhanh để bạn có thể chạy nó để hoàn thành n=4trước khi gửi nó.

Đệ trình có thể là chương trình, chức năng, vv như bình thường.

Lỗ hổng tiêu chuẩn bị cấm, như mọi khi. Đây là mã golf, vì vậy câu trả lời ngắn nhất trong byte thắng. Hãy đặt câu hỏi làm rõ trong các ý kiến.


Lâu rồi không gặp isaac!
orlp

Khi là hai tập con, có bất kỳ kịch bản nào mà có thể được suy ra từ bất kỳ thông tin nào ngoài hoặc , không tính ban đầu ? P Q P Q p P , q Q ( p q ) một b c ...P,QPQPQpP,qQ(pq)abc
orlp

Trả lời có. không đủ chặt chẽ, ví dụ: . { một , c } , { b , c }pP,qQ(pq){a,c},{b,c}
orlp

@orlp Tốt để trở lại! Tôi nghĩ rằng tôi sẽ làm hầu hết các câu hỏi cho tương lai gần
isaacg

Bạn cũng có thể thêm 14 thứ tự có thể cho n = 4?
Peter Taylor

Câu trả lời:


11

Python 3 + SciPy, 396 390 385 351 336 355 byte

from scipy.optimize import*
n=int(input())
r=range(n)
def f(u):
 s=linprog(r,u,[-n]*len(u),options={'tol':.1});c=s.success;y=sorted(range(c<<n),key=lambda a:s.x.round()@[a>>i&1for i in r])
 for a,b in zip(y,y[1:]):
  v=[(a>>i&1)-(b>>i&1)for i in r]
  if~-(v in u):c+=f(u+[[-z for z in v]]);u+=v,
 return+c
print(f([[(i==j-1)-(i==j)for i in r]for j in r]))

Hãy thử trực tuyến!

Điều này bây giờ chạy trong n = 5 trong khoảng 5 giây. Có if~-(v in u):thể được loại bỏ cho byte18 byte nhưng hình phạt hiệu năng rất lớn.

Nếu bạn muốn in tất cả các thứ tự trừu tượng như chúng được tìm thấy thay vì chỉ đếm chúng, hãy thêm if c:print(s.x.round(),y)trước forvòng lặp. (Các tập con được biểu diễn bằng số nguyên nhị phân trong đó mỗi bit tương ứng với sự hiện diện hoặc vắng mặt của một phần tử: { a , c , d } 1101₂ = 13.)

Làm thế nào nó hoạt động

fđệ quy đếm các thứ tự trừu tượng thỏa mãn một danh sách các ràng buộc nhất định. Chúng tôi bắt đầu với các khó khăn nmột , một + nb , b + nc , c + nd . Sử dụng lập trình tuyến tính, chúng tôi tìm ra giải pháp cho các ràng buộc (hoặc trả về 0 nếu không có). Trong trường hợp này, chúng tôi nhận được a = 4, b = 8, c = 12, d = 16. Chúng tôi làm tròn giải pháp cho các số nguyên , sau đó tính toán thứ tự tham chiếu bằng cách sắp xếp tất cả các tập hợp con của nó theo tổng của chúng:

{ a }, { b }, { c }, { a , b }, { d }, { a , c }, { a , d }, { b , c }, { b , d }, { a , b , c }, { c , d }, { a , b , d }, { a , c , d }, { b , c , d }, {a , b , c , d }

Việc làm tròn không thể khiến bất kỳ ràng buộc nào bị vi phạm nhiều hơn n / 2, đó là lý do tại sao chúng tôi đã thêm một lề của n .

Vì Python sortedổn định, bất kỳ mối quan hệ nào giữa các tập hợp con đều bị phá vỡ theo cùng thứ tự từ điển đảo ngược mà chúng tôi đã tạo ra chúng. Vì vậy, chúng ta có thể tưởng tượng thay thế { a , b , c , d } bằng { a · 2 ^ n + 2 ^ 0, b · 2 ^ n + 2 ^ 1, c · 2 ^ n + 2 ^ 2, d · 2 ^ n + 2 ^ 3} để có được thứ tự tương tự mà không có bất kỳ ràng buộc nào.

Kế hoạch là phân loại tất cả các thứ tự trừu tượng khác bằng phân tích trường hợp dựa trên nơi đầu tiên chúng không đồng ý với thứ tự tham chiếu:

Hoặc { a }> { b }
hoặc { a } <{ b }> { c }
hoặc { a } <{ b } <{ c }> { a , b }
hoặc { a } <{ b } < { c } <{ a , b }> { d },

Trong mỗi trường hợp, chúng tôi thêm các ràng buộc mới này với biên độ n và gọi đệ quy fvới các ràng buộc mới được thêm vào.

Ghi chú

Trong một thời gian tôi đã phỏng đoán (nhưng không cho rằng) các giải pháp chương trình tuyến tính có lề 1 trên các ràng buộc sẽ luôn là số nguyên. Điều này hóa ra là sai: một ví dụ mẫu có n = 7 là {2.5, 30, 62.5, 73.5, 82, 87.5, 99.5}.

Python, 606 byte (nhanh hơn, không có thư viện bên ngoài)

n=int(input())
r=range(n)
e=enumerate
def l(u,x):
 for i,v in e(u):
  for j,a in e(v):
   if a<0:break
  else:return[0]*len(x)
  if sum(b*x[k]for k,b in e(v))>0:
   x=l([[b*w[j]-a*w[k]for k,b in e(v)if k!=j]for w in u[:i]],x[:j]+x[j+1:]);x.insert(j,0)
   for k,b in e(v):
    if k!=j:x[j]+=b*x[k];x[k]*=-a
 return x
def f(u,x):
 x=l(u,x);c=any(x);y=sorted(range(c<<n),key=lambda a:sum(x[i]*(a>>i&1)for i in r))
 for a,b in zip(y,y[1:]):
  v=[(a>>i&1)-(b>>i&1)for i in r]+[1]
  if~-(v in u):c+=f(u+[[-z for z in v[:-1]]+[1]],x);u+=v,
 return+c
print(f([[(i==j-1)-(i==j)for i in r]+[1]for j in r],[1]*(n+1)))

Hãy thử trực tuyến!

Điều này chạy trong n = 5 trong một phần tư giây và n = 6 trong 230 giây (75 giây trong PyPy).

Nó bao gồm một bộ giải lập trình tuyến tính được mã hóa bằng tay sử dụng toán học số nguyên trong các tọa độ đồng nhất để tránh các vấn đề làm tròn điểm nổi.



@ Mr.Xcoder Chắc chắn, cảm ơn!
Anders Kaseorg

@Lynn Cảm ơn! Tôi đã thỏa hiệp một chút vì tôi không muốn làm chậm nó quá nhiều. Nó đã mất gần 3 phút cho n = 5.
Anders Kaseorg

1
@AlonAmit Có vẻ như mất khoảng 55 phút cho n = 6. SciPy không phải là tốt nhất ở LP; Tôi có một phiên bản sử dụng GLPK thay vì SciPy có n = 6 trong 70 giây. Liên quan nhiều hơn, phiên bản SciPy đã trả lời sai (và GLPK là đúng), vì vậy, đó là câu hỏi thú vị, tôi tự hỏi liệu đây có phải là SciPy # 6690 không?
Anders Kaseorg

1
@AlonAmit # 6690 không phải là nó. Nhưng tôi nói thêm options={'tol':.1}, có vẻ như sẽ giải quyết vấn đề.
Anders Kaseorg

0

Ruby, 308 byte, nhanh hơn nhiều

Chạy trường hợp 4 trong ~ 150ms. Không có thư viện chuyên ngành được sử dụng.

->n{t=2**(n-1)
n==0 ?[[0]]:P[n-1].map{|a|b=a.map{|i|i+t}
[*0..t].repeated_combination(t).select{|m|m[0]>=a.index(n-1)}.map{|m|c,d=a.dup,b.dup;m.reverse.map{|i|c.insert(i,d.pop)};c}}.flatten(1).select{|p|p.combination(2).all?{|(x,y)|x&~y==0||y&~x!=0&&n.times.all?{|i|x!=y<<i+1}&&p.index(x&~y)<p.index(y&~x)}}}

Nó đệ quy xen kẽ kết quả của một trường hợp nhỏ, ví dụ

[{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}]

với các tập hợp con tương ứng với một phần tử bổ sung được thêm vào - chúng phải giữ cùng thứ tự tương đối. Nó cũng đảm bảo rằng singleton mới được thêm vào sau tất cả các singletons trước đó.

Phần kiểm tra sự tuân thủ giống như trước đây, nhưng không phải là sự kết hợp để kiểm tra ít hơn nhiều.

Phiên bản mở rộng và nhận xét:

->n{
    t=2**(n-1)
    if n==0
        [[0]]
    else
        # for each one of the previous nice orderings
        P[n-1].map { |a|
            # create the missing sets, keep order
            b = a.map{|i|i+t}
            # intersperse the two sets
            [*0..t].repeated_combination(t) # select t insertion points
                .select do |m|
                    # ensure the new singleton is after the old ones
                    m[0] >= a.index(n-1)
                end
                .map do |m|
                    # do the interspersion
                    c,d=a.dup,b.dup
                    m.reverse.map{|i|c.insert(i, d.pop)}
                    c
                end
        }.flatten(1).select{ |p|
            # check if the final ordering is still nice
            p.combination(2).all? { |(x,y)|
                (x&~y==0) || 
                (y&~x!=0) && 
                n.times.all?{|i|x!=y<<i+1} && 
                (p.index(x&~y)<p.index(y&~x))
            }
        }
    end
}

Ruby, 151 byte, khá chậm

(trường hợp ba phần tử mất << 1s, trường hợp bốn phần tử vẫn đang chạy)

->n{[*1...2**n-1].permutation.select{|p|p.combination(2).all?{|(x,y)|x&~y==0||y&~x!=0&&n.times.all?{|i|x!=y<<i+1}&&p.index(x&~y)<p.index(y&~x)}}.count}

Nó hoạt động trên đại diện bitfield của các tập con, vì vậy người ta có thể phải xoa bóp đầu ra nếu cần để hiển thị các tập con.

định dạng:

-> n {
  [*1...2**n-1]. # prepare permutations of non-empty and non-full sets
    permutation.
    select { |p|
      p.combination(2). # check all ordered pairs
        all? { |(x, y)|
          # first is subset of second 
          x &~ y == 0 ||
          # second is not subset of first
          y &~ x != 0 &&
          # first is not a right shift of second
          # (this normalizes the ordering on atoms)
          n.times.all? { |i| x != y << i+1 } &&
          # after taking out common elements, ordering agrees 
          p.index(x &~ y) < p.index(y &~ x)
        }
    }.
    count
}

Tôi không thể kiểm tra nó trên 3 trên máy của mình nhưng cái này (139 byte) phải giống hệt về mặt giải pháp của bạn. Thay đổi: ...x-1=> ..x-2, .select{...}.count=> .count{...}, |(x,y)|=> |x,y|, x&~y==0||y&~x!=0=> x&~y<1||y&~x>0a&~bkhông thể âm nếu tôi không nhầm
Asone Tuhid

1
Nhìn vào n=5ví dụ tôi vừa thêm. Nếu tôi không nhầm, mã của bạn sẽ chấp nhận nó.
isaacg

2
Liên kết TIO cho thấy nó không hoạt động chính xác trên ví dụ: Hãy thử trực tuyến!
isaacg

1
Phiên bản mới hơn của bạn dường như là một hàm đệ quy được gọi P, vì vậy nó không thể ẩn danh. Ngoài ra, tôi nghĩ rằng nó vẫn thất bại do ví dụ tôi đã đăng.
isaacg

1
Để có giải pháp nhanh hơn: 280 byte Hãy thử trực tuyến! . Lưu ý rằng bạn phải bao gồm tên của hàm đệ quy ( P=). Ngoài ra, tôi nghĩ rằng bạn phải trả lại một số để bạn có thể phải kết hợp .sizeở đó một nơi nào đó.
Asone Tuhid
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.