माणिक, बहुत तेज, लेकिन यह इनपुट पर निर्भर करता है
अब स्ट्रिंग्स से पूर्णांक पर स्विच करके 2 ~ 2.5 के कारक द्वारा स्पीड-अप करें।
उपयोग:
cat <input> | ruby this.script.rb
उदाहरण के लिए।
mad_gaksha@madlab ~/tmp $ ruby c50138.rb < c50138.inp2
number of matches: 298208861472
took 0.05726237 s
एक एकल मास्क के लिए मैचों की संख्या द्विपद गुणांक द्वारा आसानी से गणना की जाती है। इसलिए उदाहरण के लिए 122020
3 2
एस भरे, 1 0
और 2 चाहिए 1
। इस प्रकार nCr(3,2)=nCr(3,1)=3!/(2!*1!)=3
इस मास्क से मेल खाते हुए अलग - अलग बाइनरी स्ट्रिंग्स हैं।
N मास्क m_1, m_2, ... m_n के बीच एक प्रतिच्छेदन एक मास्क q है, जैसे कि एक बाइनरी स्ट्रिंग s केवल q से मेल खाता है यदि यह सभी मास्क m_i से मेल खाता है।
यदि हम दो मास्क m_1 और m_2 लेते हैं, तो इसका प्रतिच्छेदन आसानी से गणना की जाती है। बस m_1 [i] = m_2 [i] यदि m_1 [i] == २ सेट करें। बीच चौराहे 122020
और 111222
है 111020
:
122020 (matched by 3 strings, 111000 110010 101010)
111222 (matched by 1 string, 111000)
111020 (matched by 1 string, 111000)
दो अलग-अलग मास्क 3 + 1 = 4 स्ट्रिंग्स से मेल खाते हैं, इंटरसेक्शन मास्क एक स्ट्रिंग से मेल खाता है, इस प्रकार 3 या 1-1 = 3 अद्वितीय स्ट्रिंग्स हैं जो एक या दोनों मास्क से मेल खाते हैं।
मैं N (m_1, m_2, ...) को कॉल करूंगा, जिसमें स्ट्रिंग की संख्या सभी m_i से मेल खाती है। उपरोक्त के रूप में एक ही तर्क को लागू करते हुए, हम कम से कम एक मुखौटा द्वारा मिलान किए गए अनूठे तारों की संख्या की गणना कर सकते हैं, समावेशन अपवर्जन सिद्धांत द्वारा दिया गया है और नीचे भी देखें, जैसे:
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) -+ ...
कई, कई, लेने के कई संयोजन हैं, 200 में से 30 मास्क कहते हैं।
तो यह समाधान धारणा बनाता है कि इनपुट मास्क के कई उच्च-क्रम वाले चौराहे मौजूद नहीं हैं, अर्थात। n> 2 मास्क के अधिकांश n-tuples का कोई आम मिलान नहीं होगा।
यहां कोड का उपयोग करें, ideone पर कोड आउट-डेटेड हो सकता है।
मैंने एक फ़ंक्शन जोड़ा, remove_duplicates
जिसका उपयोग इनपुट को प्री-प्रोसेस करने और मास्क को हटाने के लिए किया जा सकता है, m_i
जैसे कि यह मेल खाने वाले सभी तार एक अन्य मास्क से भी मेल खाते हैं m_j
। वर्तमान इनपुट के लिए, यह वास्तव में अधिक समय लेता है क्योंकि इस तरह के मास्क नहीं हैं (या कई नहीं)। , इसलिए फ़ंक्शन नीचे दिए गए कोड में अभी तक डेटा पर लागू नहीं है।
कोड:
# 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"
इसे समावेशन अपवर्जन सिद्धांत कहा जाता है, लेकिन इससे पहले कि कोई मुझे इसे इंगित करता है मेरे पास अपना प्रमाण था, इसलिए यहां यह जाता है। हालांकि कुछ करना अपने आप में बहुत अच्छा लगता है।
आइए 2 मास्क के मामले पर विचार करें, फिर कॉल करें 0
और 1
, पहले। हम प्रत्येक संतुलित बाइनरी स्ट्रिंग लेते हैं और इसे किस मास्क (नों) के अनुसार वर्गीकृत करते हैं, यह मेल खाता है। c0
उन है कि केवल मेल खाते हैं मुखौटा की संख्या है 0
, c1
जो केवल मेल खाते की nunber 1
, c01
उन है कि मैच मुखौटा 0
और 1
।
आज्ञा दें s0
कि प्रत्येक मास्क के लिए माचिस की संख्या का योग (वे ओवरलैप हो सकते हैं)। आज्ञा दें s1
कि प्रत्येक जोड़ी (2-संयोजन) के मास्क की संख्या का योग है। आज्ञा देना s_i
प्रत्येक के लिए मैचों की संख्या का योग हो (i + 1) मास्क का संयोजन। एन-मास्क के मैचों की संख्या बाइनरी स्ट्रिंग्स की संख्या है जो सभी मास्क से मेल खाती है।
यदि n मास्क हैं, तो वांछित आउटपुट सभी का योग है c
, अर्थात। c = c0+...+cn+c01+c02+...+c(n-2)(n-1)+c012+...+c(n-3)(n-2)(n-1)+...+c0123...(n-2)(n-1)
। कार्यक्रम की गणना सभी की वैकल्पिक राशि है s
, अर्थात। s = s_0-s_1+s_2-+...+-s_(n-1)
। हम इसका प्रमाण देना चाहते हैं s==c
।
n = 1 स्पष्ट है। N = 2 पर विचार करें। मास्क के सभी मैचों की गिनती, 0
देता है c0+c01
(केवल मिलान करने वाले तार की संख्या 0 + जो दोनों से मेल खाते हैं ) 0
और देता है 1
, सभी मैचों की गिनती 1
करता है c1+c02
। हम इसका वर्णन इस प्रकार कर सकते हैं:
0: c0 c01
1: c1 c10
परिभाषा के अनुसार, s0 = c0 + c1 + c12
। यानी s1
के प्रत्येक 2-संयोजन के मैचों की संख्या है [0,1]
। सभी uniqye c_ij
एस। ध्यान रखें कि c01=c10
।
s0 = c0 + c1 + 2 c01
s1 = c01
s = s0 - s1 = c0 + c1 + c01 = c
इस प्रकार s=c
n = 2 के लिए।
अब 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
इस प्रकार s=c
n = 3 के लिए। c__i
सभी के c
साथ (i + 1) सूचकांकों का प्रतिनिधित्व करता है , उदाहरण के c__1 = c01
लिए n = 2 और c__1 = c01 + c02 + c12
n == 3 के लिए।
N = 4 के लिए, एक पैटर्न उभरने लगता है:
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
इस प्रकार s==c
n = 4 के लिए।
सामान्य तौर पर, हमें इस तरह के द्विपद गुणांक मिलते हैं (i i, → 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 . . .
. .
. .
. .
इसे देखने के लिए, इस बात पर विचार करें कि कुछ i
और j
हैं:
- x = ncr (n, i + 1): n के बाहर (i + 1) मास्क के प्रतिच्छेदन के लिए संयोजन C
- y = ncr (ni-1, ji): ऊपर दिए गए प्रत्येक संयोजन C के लिए, (J + 2) मास्क के चौराहे के लिए y अलग संयोजन होते हैं, जिनमें से C होते हैं।
- z = ncr (n, j + 1): n के चौराहे (j + 1) मास्क के लिए अलग-अलग संयोजन
जैसा कि भ्रामक लग सकता है, यहाँ एक उदाहरण पर लागू किया गया विक्षेप है। I = 1, j = 2, n = 4 के लिए, यह ऐसा दिखता है (ऊपर cf.):
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
तो यहाँ x = 6 (01, 02, 03, 12, 13, 23), y = 2 (प्रत्येक संयोजन के लिए दो सी तीन सूचकांकों के साथ), z = 4 (c012, c013, c023, c123)।
कुल में, (j + 1) सूचकांकों के साथ x*y
गुणांक होते हैं c
, और z
अलग - अलग होते हैं, इसलिए प्रत्येक x*y/z
बार होता है, जिसे हम गुणांक कहते हैं k_ij
। साधारण बीजगणित के द्वारा, हम प्राप्त करते हैंk_ij = ncr(n,i+1) ncr(n-i-1,j-i) / ncr(n,j+1) = ncr(j+1,i+1)
।
इसलिए इंडेक्स k_ij = nCr(j+1,i+1)
यदि आप सभी डिफेक्ट को याद करते हैं, तो हमें यह बताना होगा कि हमें प्रत्येक कॉलम का वैकल्पिक योग 1 देता है।
वैकल्पिक राशि s0 - s1 + s2 - s3 +- ... +- s(n-1)
इस प्रकार व्यक्त की जा सकती है:
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
इस प्रकार s=c
सभी n = 1,2,3 के लिए, ...