রুবি, বেশ দ্রুত, তবে এটি ইনপুটটির উপর নির্ভর করে
স্ট্রিং থেকে পূর্ণসংখ্যায় পরিবর্তন করে এখন 2 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 এর সাথে মেলে তবেই যদি এটি সমস্ত মুখোশ m_i এর সাথে মেলে।
আমরা যদি m_1 এবং m_2 দুটি মুখোশ নিই তবে এর ছেদটি সহজেই গণনা করা যায়। M_1 [i] = m_2 [i] সবেমাত্র m_1 [i] == 2 সেট করুন। 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 টি এক বা উভয় মুখোশের সাথে মিলছে unique
আমি 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 টি মাস্ক।
সুতরাং এই সমাধানটি অনুমান করে যে ইনপুট মাস্কগুলির অনেকগুলি উচ্চ-অর্ডার ছেদ নেই, যেমন। বেশিরভাগ এন-টিপলস এন> 2 মাস্কগুলিতে কোনও সাধারণ মিল নেই।
কোডটি এখানে ব্যবহার করুন, আদর্শের কোডটি পুরানো হতে পারে।
আমি একটি ফাংশন যুক্ত করেছি 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
এবং call 1
আমরা প্রতিটি সুষম বাইনারি স্ট্রিং নিয়ে থাকি এবং এটি কোন মাস্ক (গুলি) এর সাথে মেলে তার শ্রেণিবদ্ধ করে। c0
ঐ যে শুধুমাত্র মেলে মাস্ক সংখ্যা 0
, c1
ঐ যে শুধুমাত্র মেলে এর nunber 1
, c01
ঐ যে ম্যাচ মাস্ক 0
এবং 1
।
দিন s0
(তারা ওভারল্যাপ পারে) প্রতিটি মাস্ক জন্য ম্যাচ সংখ্যা সংখ্যা সমষ্টি হও। যাক s1
মুখোশ প্রতিটি জোড়া (2- সমন্বয়) জন্য ম্যাচ সংখ্যা এর সমষ্টি হও। দিন s_i
প্রতিটি (ঝ + 1) মুখোশ সংযুক্তির জন্য ম্যাচ সংখ্যা এর সমষ্টি হও। এন-মাস্কের মিলগুলির সংখ্যা হ'ল সমস্ত মাস্কের সাথে মেলে বাইনারি স্ট্রিংয়ের সংখ্যা।
যদি এন মাস্ক থাকে তবে কাঙ্ক্ষিত আউটপুট হ'ল সকলের সমষ্টি 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 সুস্পষ্ট। এন = 2 বিবেচনা করুন। মাস্ক সব ম্যাচ গণনা 0
দেয় c0+c01
(শুধুমাত্র 0 টি + ঐ ম্যাচিং উভয় মিলে স্ট্রিং সংখ্যা 0
এবং 1
), সব ম্যাচের বেড়ে চলেছে 1
দেয় c1+c02
। আমরা নিম্নলিখিত হিসাবে এটি বর্ণনা করতে পারেন:
0: c0 c01
1: c1 c10
সংজ্ঞা দ্বারা s0 = c0 + c1 + c12
,। s1
হ'ল প্রতিটি 2-সংমিশ্রণের মিলগুলির সংখ্যার [0,1]
অর্থাত্। সমস্ত ইউনিট c_ij
s। মনে রাখবেন c01=c10
।
s0 = c0 + c1 + 2 c01
s1 = c01
s = s0 - s1 = c0 + c1 + c01 = c
এভাবে s=c
এন = 2 এর জন্য।
এখন এন = 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
এন = 3 এর জন্য। c__i
সব প্রতিনিধিত্ব করে c
(আমি + 1) সূচকের যেমন সঙ্গে গুলি c__1 = c01
এন = 2 এবং c__1 = c01 + c02 + c12
ঢ == 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
এন = 4 এর জন্য।
সাধারণভাবে, আমরা এর মতো দ্বিপদী সহগগুলি পাই (get আমি,, হ'ল জে):
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 = এনসিআর (এন, আই + 1): সংযোগ সি সি থেকে (i + 1) মুখোশের ছেদ জন্য
- y = এনসিআর (এনআই -১, জি): উপরের প্রতিটি সংমিশ্রণের জন্য, সি রয়েছে এমনগুলির মধ্যে (জে + ২) মুখোশের ছেদ করার জন্য y বিভিন্ন সংমিশ্রণ রয়েছে
- z = এনসিআর (এন, জে + 1): এন এর বাইরে (জে + 1) মুখোশের ছেদ করার জন্য বিভিন্ন সংমিশ্রণ
যেহেতু বিভ্রান্তিমূলক মনে হতে পারে, এখানে একটি উদাহরণের সাথে সংজ্ঞাটি প্রয়োগ করা হয়েছে। I = 1, j = 2, n = 4 এর জন্য দেখতে এটি দেখতে (সিএফ। উপরে):
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)।
মোট, (জে + 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
সমস্ত এন = 1,2,3, ...