rubi, bem rápido, mas depende da entrada
Agora acelere por um fator de 2 ~ 2,5, alternando de cadeias para números inteiros.
Uso:
cat <input> | ruby this.script.rb
Por exemplo.
mad_gaksha@madlab ~/tmp $ ruby c50138.rb < c50138.inp2
number of matches: 298208861472
took 0.05726237 s
O número de correspondências para uma única máscara é prontamente calculado pelo coeficiente binomial. Por exemplo, 122020precisa de 3 2s preenchidos, 1 0e 2 1. Portanto, existem nCr(3,2)=nCr(3,1)=3!/(2!*1!)=3diferentes cadeias binárias correspondentes a essa máscara.
Uma interseção entre n máscaras m_1, m_2, ... m_n é uma máscara q, de modo que uma sequência binária s corresponda a q somente se corresponder a todas as máscaras m_i.
Se usarmos duas máscaras m_1 e m_2, sua interseção é facilmente calculada. Basta definir m_1 [i] = m_2 [i] se m_1 [i] == 2. A interseção entre 122020e 111222é 111020:
122020 (matched by 3 strings, 111000 110010 101010)
111222 (matched by 1 string, 111000)
111020 (matched by 1 string, 111000)
As duas máscaras individuais são correspondidas por 3 + 1 = 4 strings, a máscara de interseção é correspondida por uma string, portanto, existem 3 + 1-1 = 3 strings únicas que correspondem a uma ou ambas as máscaras.
Vou chamar N (m_1, m_2, ...) o número de cadeias correspondentes a todos m_i. Aplicando a mesma lógica acima, podemos calcular o número de seqüências únicas correspondidas por pelo menos uma máscara, fornecidas pelo princípio de exclusão de inclusão e ver abaixo também, assim:
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) -+ ...
Existem muitas, muitas, muitas combinações de tomar, digamos, 30 máscaras em 200.
Portanto, esta solução assume que não existem muitas interseções de alta ordem das máscaras de entrada, ou seja. a maioria das n-tuplas de n> 2 máscaras não terá correspondências comuns.
Use o código aqui, o código da ideone pode estar desatualizado.
Adicionei uma função remove_duplicatesque pode ser usada para pré-processar a entrada e excluir máscaras, de m_imodo que todas as seqüências correspondentes a ela também correspondam a outra máscara m_j. , portanto, a função ainda não está aplicada aos dados no código abaixo.
Código:
# 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"
Isso é chamado de princípio de exclusão de inclusão, mas antes que alguém me apontasse, eu tinha minha própria prova, então aqui está. Fazer algo você mesmo é ótimo.
Vamos considerar o caso de 2 máscaras, ligue então 0e 1, primeiro. Pegamos todas as seqüências binárias balanceadas e as classificamos de acordo com a (s) máscara (s) correspondente (s). c0é o número daqueles que correspondem apenas à máscara 0, c1o número dos que correspondem apenas 1, c01aqueles que correspondem à máscara 0e 1.
Seja s0a soma numérica do número de correspondências para cada máscara (elas podem se sobrepor). Seja s1a soma do número de correspondências para cada par (2 combinações) de máscaras. Deixeis_i a soma do número de correspondências para cada combinação (i + 1) de máscaras. O número de correspondências de n-máscaras é o número de cadeias binárias que correspondem a todas as máscaras.
Se houver n máscaras, a saída desejada é a soma de todos c, ie. c = c0+...+cn+c01+c02+...+c(n-2)(n-1)+c012+...+c(n-3)(n-2)(n-1)+...+c0123...(n-2)(n-1). O que o programa calcula é a soma alternada de todos s's, ie. s = s_0-s_1+s_2-+...+-s_(n-1). Desejamos provar isso s==c.
n = 1 é óbvio. Considere n = 2. Contando todas as correspondências de máscara 0dá c0+c01(o número de cadeias correspondendo apenas 0 + as que correspondem a ambos 0e 1), contando todas as correspondências de 1ofertas c1+c02. Podemos ilustrar isso da seguinte maneira:
0: c0 c01
1: c1 c10
Por definição s0 = c0 + c1 + c12,. s1é o número soma de correspondências de cada combinação 2 de [0,1], ie. todos uniqye c_ijs. Lembre-se disso c01=c10.
s0 = c0 + c1 + 2 c01
s1 = c01
s = s0 - s1 = c0 + c1 + c01 = c
Assim, s=cpara n = 2.
Agora considere 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
Assim, s=cpara n = 3. c__irepresenta o de todos os cs com (i + 1) índices, por exemplo, c__1 = c01para n = 2 e c__1 = c01 + c02 + c12para n == 3.
Para n = 4, um padrão começa a emergir:
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
Assim, s==cpara n = 4.
Em geral, obtemos coeficientes binomiais como este (↓ é 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 . . .
. .
. .
. .
Para ver isso, considere isso para alguns ie j, existem:
- x = ncr (n, i + 1): combinações C para a interseção de (i + 1) máscara de n
- y = ncr (ni-1, ji): para cada combinação C acima, existem y combinações diferentes para a interseção de (j + 2) máscaras daquelas que contêm C
- z = ncr (n, j + 1): combinações diferentes para a interseção de (j + 1) máscaras de n
Como isso pode parecer confuso, aqui está a definição aplicada a um exemplo. Para i = 1, j = 2, n = 4, fica assim (cf. acima):
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
Portanto, aqui x = 6 (01, 02, 03, 12, 13, 23), y = 2 (dois c com três índices para cada combinação), z = 4 (c012, c013, c023, c123).
No total, existem x*ycoeficientes ccom índices (j + 1), e existem zdiferentes, portanto, cada um ocorre x*y/zvezes, que chamamos de coeficiente k_ij. Por álgebra simples, obtemos k_ij = ncr(n,i+1) ncr(n-i-1,j-i) / ncr(n,j+1) = ncr(j+1,i+1).
Portanto, o índice é dado por k_ij = nCr(j+1,i+1)Se você se lembrar de todas as definições, tudo o que precisamos mostrar é que a soma alternada de cada coluna fornece 1.
A soma alternada s0 - s1 + s2 - s3 +- ... +- s(n-1)pode assim ser expressa como:
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
Assim, s=cpara todos n = 1,2,3, ...