ruby, khá nhanh, nhưng nó phụ thuộc vào đầu vào
Bây giờ tăng tốc theo hệ số 2 ~ 2,5 bằng cách chuyển từ chuỗi sang số nguyên.
Sử dụng:
cat <input> | ruby this.script.rb
Ví dụ.
mad_gaksha@madlab ~/tmp $ ruby c50138.rb < c50138.inp2
number of matches: 298208861472
took 0.05726237 s
Số lượng các trận đấu cho một mặt nạ duy nhất được tính bằng hệ số nhị thức. Vì vậy, ví dụ 122020
cần 3 2
s đầy, 1 0
và 2 1
. Do đó, có nCr(3,2)=nCr(3,1)=3!/(2!*1!)=3
các chuỗi nhị phân khác nhau phù hợp với mặt nạ này.
Giao điểm giữa n mặt nạ m_1, m_2, ... m_n là mặt nạ q, sao cho chuỗi nhị phân s khớp với q chỉ khi nó khớp với tất cả các mặt nạ m_i.
Nếu chúng ta lấy hai mặt nạ m_1 và m_2, giao điểm của nó dễ dàng được tính toán. Chỉ cần đặt m_1 [i] = m_2 [i] nếu m_1 [i] == 2. Giao điểm giữa 122020
và 111222
là 111020
:
122020 (matched by 3 strings, 111000 110010 101010)
111222 (matched by 1 string, 111000)
111020 (matched by 1 string, 111000)
Hai mặt nạ riêng lẻ được khớp bởi 3 + 1 = 4 chuỗi, mặt nạ xen kẽ được khớp bởi một chuỗi, do đó có 3 + 1-1 = 3 chuỗi duy nhất khớp với một hoặc cả hai mặt nạ.
Tôi sẽ gọi N (m_1, m_2, ...) số chuỗi khớp với tất cả m_i. Áp dụng logic tương tự như trên, chúng ta có thể tính toán số chuỗi duy nhất khớp với ít nhất một mặt nạ, được đưa ra theo nguyên tắc loại trừ bao gồm và xem bên dưới, như sau:
N(m_1) + N(m_2) + ... + N(m_n) - N(m_1,m_2) - ... - N(m_n-1,m_n) + N(m_1,m_2,m_3) + N(m_1,m_2,m_4) + ... N(m_n-2,m_n-1,m_n) - N(m_1,m_2,m_3,m_4) -+ ...
Có rất nhiều, rất nhiều, rất nhiều sự kết hợp của việc dùng, nói 30 mặt nạ trong số 200.
Vì vậy, giải pháp này đưa ra giả định rằng không có nhiều giao điểm bậc cao của mặt nạ đầu vào tồn tại, tức là. hầu hết n-tuples của n> 2 mặt nạ sẽ không có bất kỳ kết quả khớp nào.
Sử dụng mã ở đây, mã tại ideone có thể bị lỗi thời.
Tôi đã thêm một chức năng remove_duplicates
có thể được sử dụng để xử lý trước các mặt nạ đầu vào và xóa m_i
sao cho tất cả các chuỗi khớp với nó cũng khớp với mặt nạ khác m_j
. Đối với đầu vào hiện tại, việc này thực sự mất nhiều thời gian hơn vì không có mặt nạ nào như vậy (hoặc không nhiều) , do đó, hàm không được áp dụng cho dữ liệu trong mã bên dưới.
Mã số:
# factorial table
FAC = [1]
def gen_fac(n)
n.times do |i|
FAC << FAC[i]*(i+1)
end
end
# generates a mask such that it is matched by each string that matches m and n
def diff_mask(m,n)
(0..m.size-1).map do |i|
c1 = m[i]
c2 = n[i]
c1^c2==1 ? break : c1&c2
end
end
# counts the number of possible balanced strings matching the mask
def count_mask(m)
n = m.size/2
c0 = n-m.count(0)
c1 = n-m.count(1)
if c0<0 || c1<0
0
else
FAC[c0+c1]/(FAC[c0]*FAC[c1])
end
end
# removes masks contained in another
def remove_duplicates(m)
m.each do |x|
s = x.join
m.delete_if do |y|
r = /\A#{s.gsub(?3,?.)}\Z/
(!x.equal?(y) && y =~ r) ? true : false
end
end
end
#intersection masks of cn masks from m.size masks
def mask_diff_combinations(m,n=1,s=m.size,diff1=[3]*m[0].size,j=-1,&b)
(j+1..s-1).each do |i|
diff2 = diff_mask(diff1,m[i])
if diff2
mask_diff_combinations(m,n+1,s,diff2,i,&b) if n<s
yield diff2,n
end
end
end
# counts the number of balanced strings matched by at least one mask
def count_n_masks(m)
sum = 0
mask_diff_combinations(m) do |mask,i|
sum += i%2==1 ? count_mask(mask) : -count_mask(mask)
end
sum
end
time = Time.now
# parse input
d = STDIN.each_line.map do |line|
line.chomp.strip.gsub('2','3')
end
d.delete_if(&:empty?)
d.shift
d.map!{|x|x.chars.map(&:to_i)}
# generate factorial table
gen_fac([d.size,d[0].size].max+1)
# count masks
puts "number of matches: #{count_n_masks(d)}"
puts "took #{Time.now-time} s"
Điều này được gọi là nguyên tắc loại trừ bao gồm, nhưng trước khi ai đó chỉ cho tôi, tôi đã có bằng chứng của riêng mình, vì vậy nó sẽ đi. Làm một cái gì đó bản thân bạn cảm thấy tuyệt vời mặc dù.
Hãy để chúng tôi xem xét trường hợp của 2 mặt nạ, gọi sau đó 0
và 1
, đầu tiên. Chúng tôi lấy mọi chuỗi nhị phân cân bằng và phân loại nó theo mặt nạ mà nó khớp. c0
là số lượng những người chỉ phù hợp với mặt nạ 0
, c1
nữ tu sĩ của những người chỉ phù hợp với 1
, c01
những người phù hợp với mặt nạ 0
và 1
.
Gọi s0
là tổng số của số lượng khớp cho mỗi mặt nạ (chúng có thể trùng nhau). Gọi s1
là tổng số lượng trận đấu cho mỗi cặp (2 kết hợp) mặt nạ. Gọi s_i
là tổng số lượng các trận đấu cho mỗi kết hợp (i + 1) của mặt nạ. Số lượng kết hợp của mặt nạ n là số chuỗi nhị phân khớp với tất cả các mặt nạ.
Nếu có n mặt nạ, đầu ra mong muốn là tổng của tất cả c
, nghĩa là. c = c0+...+cn+c01+c02+...+c(n-2)(n-1)+c012+...+c(n-3)(n-2)(n-1)+...+c0123...(n-2)(n-1)
. Những gì chương trình tính toán là tổng xen kẽ của tất cả s
, tức là. s = s_0-s_1+s_2-+...+-s_(n-1)
. Chúng tôi muốn chứng minh điều đó s==c
.
n = 1 là hiển nhiên. Xét n = 2. Đếm tất cả các trận đấu của mặt nạ 0
cho c0+c01
(số lượng chuỗi phù hợp với chỉ 0 + những hợp cả hai 0
và 1
), đếm tất cả các trận đấu của 1
cho c1+c02
. Chúng ta có thể minh họa điều này như sau:
0: c0 c01
1: c1 c10
Theo định nghĩa , s0 = c0 + c1 + c12
. s1
là tổng số trận đấu của mỗi kết hợp 2 [0,1]
, nghĩa là. tất cả uniqye c_ij
s. Hãy ghi nhớ điều đó c01=c10
.
s0 = c0 + c1 + 2 c01
s1 = c01
s = s0 - s1 = c0 + c1 + c01 = c
Do đó s=c
với n = 2.
Bây giờ hãy xem xét n = 3.
0 : c0 + c01 + c02 + c012
1 : c1 + c01 + c12 + c012
2 : c2 + c12 + c02 + c012
01 : c01 + c012
02 : c02 + c012
12 : c12 + c012
012: c012
s0 = c0 + c1 + c2 + 2 (c01+c02+c03) + 3 c012
s1 = c01 + c02 + c12 + 3 c012
s2 = c012
s0 = c__0 + 2 c__1 + 3 c__2
s1 = c__1 + 3 c__2
s2 = c__2
s = s0 - s1 + s2 = ... = c0 + c1 + c2 + c01 + c02 + c03 + c012 = c__0 + c__1 + c__2 = c
Do đó s=c
với n = 3. c__i
đại diện cho tất cả các c
s với (i + 1) chỉ số, ví dụ c__1 = c01
cho n = 2 và c__1 = c01 + c02 + c12
cho n == 3.
Với n = 4, một mẫu bắt đầu xuất hiện:
0: c0 + c01 + c02 + c03 + c012 + c013 + c023 + c0123
1: c1 + c01 + c12 + c13 + c102 + c103 + c123 + c0123
2: c2 + c02 + c12 + c23 + c201 + c203 + c213 + c0123
3: c3 + c03 + c13 + c23 + c301 + c302 + c312 + c0123
01: c01 + c012 + c013 + c0123
02: c02 + c012 + c023 + c0123
03: c03 + c013 + c023 + c0123
12: c11 + c012 + c123 + c0123
13: c13 + c013 + c123 + c0123
23: c23 + c023 + c123 + c0123
012: c012 + c0123
013: c013 + c0123
023: c023 + c0123
123: c123 + c0123
0123: c0123
s0 = c__0 + 2 c__1 + 3 c__2 + 4 c__3
s1 = c__1 + 3 c__2 + 6 c__3
s2 = c__2 + 4 c__3
s3 = c__3
s = s0 - s1 + s2 - s3 = c__0 + c__1 + c__2 + c__3 = c
Do đó s==c
với n = 4.
Nói chung, chúng tôi nhận được các hệ số nhị thức như thế này (là i, → là j):
0 1 2 3 4 5 6 . . .
0 1 2 3 4 5 6 7 . . .
1 1 3 6 10 15 21 . . .
2 1 4 10 20 35 . . .
3 1 5 15 35 . . .
4 1 6 21 . . .
5 1 7 . . .
6 1 . . .
. .
. .
. .
Để thấy điều này, hãy xem xét điều đó đối với một số i
và j
, có:
- x = ncr (n, i + 1): kết hợp C cho giao điểm của (i + 1) mặt nạ ngoài n
- y = ncr (ni-1, ji): với mỗi kết hợp C ở trên, có y kết hợp khác nhau cho giao điểm của (j + 2) trong số các kết hợp có chứa C
- z = ncr (n, j + 1): các kết hợp khác nhau cho giao điểm của (j + 1) mặt nạ ngoài n
Vì điều đó nghe có vẻ khó hiểu, đây là định nghĩa được áp dụng cho một ví dụ. Với i = 1, j = 2, n = 4, nó trông như thế này (xem ở trên):
01: c01 + c012 + c013 + c0123
02: c02 + c012 + c023 + c0123
03: c03 + c013 + c023 + c0123
12: c11 + c012 + c123 + c0123
13: c13 + c013 + c123 + c0123
23: c23 + c023 + c123 + c0123
Vì vậy, ở đây x = 6 (01, 02, 03, 12, 13, 23), y = 2 (hai c với ba chỉ số cho mỗi kết hợp), z = 4 (c012, c013, c023, c123).
Tổng cộng, có các x*y
hệ số c
với (j + 1) chỉ số và có các hệ số z
khác nhau, do đó, mỗi x*y/z
lần xảy ra , chúng tôi gọi là hệ số k_ij
. Bằng đại số đơn giản, chúng tôi nhận được k_ij = ncr(n,i+1) ncr(n-i-1,j-i) / ncr(n,j+1) = ncr(j+1,i+1)
.
Vì vậy, chỉ số được đưa ra bởi k_ij = nCr(j+1,i+1)
Nếu bạn nhớ lại tất cả các khuyết điểm, tất cả những gì chúng ta cần chỉ ra là tổng số xen kẽ của mỗi cột cho 1.
s0 - s1 + s2 - s3 +- ... +- s(n-1)
Do đó, tổng xen kẽ có thể được biểu thị như sau:
s_j = c__j * ∑[(-1)^(i+j) k_ij] for i=0..n-1
= c__j * ∑[(-1)^(i+j) nCr(j+1,i+1)] for i=0..n-1
= c__j * ∑[(-1)^(i+j) nCr(j+1,i)]{i=0..n} - (-1)^0 nCr(j+1,0)
= (-1)^j c__j
s = ∑[(-1)^j s_j] for j = 0..n-1
= ∑[(-1)^j (-1)^j c__j)] for j=0..n-1
= ∑[c__j] for j=0..n-1
= c
Do đó s=c
với mọi n = 1,2,3, ...