Uma string binária é uma string que contém apenas caracteres extraídos de 01 . A cadeia binária equilibrada é uma string binário que contém exatamente como muitos 0 s como 1 s.
Você recebe um número inteiro positivo n e um número arbitrário de máscaras, cada uma com 2n caracteres e contém apenas caracteres extraídos de 012 . Uma string binária e uma máscara correspondem se tiverem o mesmo comprimento e concordarem com o caractere em todas as posições em que a máscara não tiver um 2 . Por exemplo, a máscara 011022 corresponde às cadeias binárias 011000 , 011001 , 011010 , 011011 .
Dado n e as máscaras como entrada (separadas por novas linhas), você deve gerar o número de seqüências binárias balanceadas distintas que correspondem a uma ou mais das máscaras.
Exemplos
Entrada
3
111222
000112
122020
122210
102120
Raciocínio
- A única string binária balanceada correspondente a 111222 é 111000 .
- A única string binária balanceada correspondente a 000112 é 000111 .
- As cadeias binárias balanceadas correspondentes a 122020 são 111000 (já contadas), 110010 e 101010 .
- As cadeias binárias balanceadas correspondentes a 122210 são 110010 (já contadas), 101010 (já contadas) e 100110 .
- As cadeias binárias balanceadas correspondentes 102120 é 101100 e 100110 (já contava).
Portanto, a saída deve ser
6
Entrada
10
22222222222222222222
Raciocínio
- Existem 20 opções para escolher 10 seqüências binárias balanceadas de comprimento 20.
Resultado
184756
Vencedora
O vencedor será aquele que calcular a entrada da competição o mais rápido, tratando-a da mesma maneira que faria com qualquer outra entrada. (Eu uso um código determinado para ter um vencedor claro e evitar casos em que entradas diferentes dariam vencedores diferentes. Se você pensar em uma maneira melhor de encontrar o código mais rápido, me diga).
Participação na competição
fonte
Respostas:
C
Se você não estiver no Linux ou tiver problemas para compilar, provavelmente remova o código de temporização (
clock_gettime
).Casos de exemplo:
(Os horários são para uma CPU i7-4770K a 4.1 GHz.) Cuidado,
testcase-hard
use cerca de 3-4 GB de memória.Isso é basicamente uma implementação do método de inclusão-exclusão que o blutorange criou, mas feito para que ele lide com interseções de qualquer profundidade.
O código escrito está gastando muito tempo na alocação de memória e ficará ainda mais rápido quando eu otimizar o gerenciamento de memória.Eu reduzi cerca de 25%
testcase-hard
, mas o desempenho no original (testcase-long
) permanece praticamente inalterado, já que não há muita alocação de memória. Vou ajustar um pouco mais antes de chamá-lo: acho que também posso obter uma melhoria de 25% a 50%testcase-long
.Mathematica
Depois que percebi que era um problema do #SAT, percebi que poderia usar o built-in do Mathematica
SatisfiabilityCount
:Resultado:
São 298.208.861.472 máscaras em 1,3 segundos (i7-3517U a 1,9 GHz), incluindo o tempo gasto no download do caso de teste do pastebin.
fonte
testcase-hard
pode ser concluído muito rapidamente se o seu código procurar máscaras que possam ser combinadas. Se o seu código fizer isso, exclua todas as outras linhas (apenas os/^2*02*$/
casos permanecem). Não acho que esse caso possa ser otimizado.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:
Por exemplo.
O número de correspondências para uma única máscara é prontamente calculado pelo coeficiente binomial. Por exemplo,
122020
precisa de 32
s preenchidos, 10
e 21
. Portanto, existemnCr(3,2)=nCr(3,1)=3!/(2!*1!)=3
diferentes 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
122020
e111222
é111020
: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:
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_duplicates
que pode ser usada para pré-processar a entrada e excluir máscaras, dem_i
modo que todas as seqüências correspondentes a ela também correspondam a outra máscaram_j
. , portanto, a função ainda não está aplicada aos dados no código abaixo.Código:
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
0
e1
, 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áscara0
,c1
o número dos que correspondem apenas1
,c01
aqueles que correspondem à máscara0
e1
.Seja
s0
a soma numérica do número de correspondências para cada máscara (elas podem se sobrepor). Sejas1
a 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 todoss
's, ie.s = s_0-s_1+s_2-+...+-s_(n-1)
. Desejamos provar issos==c
.n = 1 é óbvio. Considere n = 2. Contando todas as correspondências de máscara
0
dác0+c01
(o número de cadeias correspondendo apenas 0 + as que correspondem a ambos0
e1
), contando todas as correspondências de1
ofertasc1+c02
. Podemos ilustrar isso da seguinte maneira: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 uniqyec_ij
s. Lembre-se dissoc01=c10
.Assim,
s=c
para n = 2.Agora considere n = 3.
Assim,
s=c
para n = 3.c__i
representa o de todos osc
s com (i + 1) índices, por exemplo,c__1 = c01
para n = 2 ec__1 = c01 + c02 + c12
para n == 3.Para n = 4, um padrão começa a emergir:
Assim,
s==c
para n = 4.Em geral, obtemos coeficientes binomiais como este (↓ é i, → é j):
Para ver isso, considere isso para alguns
i
ej
, existem: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):
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*y
coeficientesc
com índices (j + 1), e existemz
diferentes, portanto, cada um ocorrex*y/z
vezes, que chamamos de coeficientek_ij
. Por álgebra simples, obtemosk_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:Assim,
s=c
para todos n = 1,2,3, ...fonte
0011 < 2211
,0022 < 0222
. Eu acho que isso faz com que os grupos não sejam maiores do que2*n
, embora ainda seja muito grande no pior dos casos.unifying two masks
termo,union
faz sentido para mim e eu posso definir dessa maneira, mas você está certo, no interesse da compreensão mútua que eu chavei. @ Agawa001 Você pode ser mais específico? Além disso, se você tiver uma boa idéia para tornar isso mais rápido, sinta-se à vontade para usar as idéias desta resposta em seu programa / resposta. Por enquanto, é rápido o suficiente para o caso de teste grande e, se for multiencadeado, deve demorar <0,1s, o que está abaixo de qualquer medição / comparação significativa, portanto, para casos de teste mais difíceis são necessários.C
Boa sorte para que a grande entrada seja executada - provavelmente levará a noite toda para passar aprox. 60 ^ 30 permutações! Talvez um conjunto de dados de tamanho intermediário possa ser uma boa ideia?
fonte