Une chaîne binaire est une chaîne qui ne contient que des caractères tirés de 01 . Une chaîne binaire équilibrée est une chaîne binaire qui contient exactement autant de 0 s que 1 s.
On vous donne un entier positif n et un nombre arbitraire de masques, chacun de 2n caractères et ne contenant que des caractères tirés de 012 . Une chaîne binaire et un masque correspondent s'ils ont la même longueur et s'accordent sur le caractère dans chaque position où le masque n'a pas de 2 . Par exemple, le masque 011022 correspond aux chaînes binaires 011000 , 011001 , 011010 , 011011 .
Étant donné n et les masques en entrée (séparés par des retours à la ligne), vous devez sortir le nombre de chaînes binaires équilibrées distinctes qui correspondent à un ou plusieurs des masques.
Exemples
Contribution
3
111222
000112
122020
122210
102120
Raisonnement
- La seule chaîne binaire équilibrée correspondant à 111222 est 111000 .
- La seule chaîne binaire équilibrée correspondant à 000112 est 000111 .
- Les chaînes binaires équilibrées correspondant à 122020 sont 111000 (déjà comptées), 110010 et 101010 .
- Les chaînes binaires équilibrées correspondant à 122210 sont 110010 (déjà comptées), 101010 (déjà comptées) et 100110 .
- Les chaînes binaires équilibrées correspondant à 102120 sont 101100 et 100110 (déjà comptées).
La sortie doit donc être
6
Contribution
10
22222222222222222222
Raisonnement
- Il y a 20 choisissez 10 chaînes binaires équilibrées de longueur 20.
Production
184756
Gagnant
Le vainqueur sera celui qui calculera le plus rapidement les entrées de la compétition, en les traitant bien sûr de la même manière que n'importe quelle autre entrée. (J'utilise un code déterminé afin d'avoir un gagnant clair et d'éviter les cas où différentes entrées donneraient différents gagnants. Si vous pensez à une meilleure façon de trouver le code le plus rapide, dites-le-moi).
Réponses:
C
Si vous n'êtes pas sous Linux, ou si vous rencontrez des problèmes de compilation, vous devriez probablement supprimer le code de synchronisation (
clock_gettime
).Exemples de cas:
(Les temps sont pour un processeur i7-4770K à 4,1 GHz.) Attention,
testcase-hard
utilise environ 3-4 Go de mémoire.C'est à peu près une implémentation de la méthode d'inclusion-exclusion proposée par blutorange, mais faite de manière à gérer les intersections de n'importe quelle profondeur.
Le code tel qu'il est écrit consacre beaucoup de temps à l'allocation de mémoire et sera encore plus rapide une fois que j'optimiserai la gestion de la mémoire.J'ai réduit d'environ 25%
testcase-hard
, mais les performances sur l'original (testcase-long
) sont à peu près inchangées, car il n'y a pas beaucoup d'allocation de mémoire. Je vais régler un peu plus avant de l'appeler: je pense que je pourrais peut-être aussi obtenir une amélioration de 25% à 50%testcase-long
.Mathematica
Une fois que j'ai remarqué qu'il s'agissait d'un problème #SAT, j'ai réalisé que je pouvais utiliser la fonction intégrée de Mathematica
SatisfiabilityCount
:Production:
Cela représente 298 208 861 472 masques en 1,3 seconde (i7-3517U @ 1,9 GHz), y compris le temps passé à télécharger le cas de test à partir de pastebin.
la source
testcase-hard
peut être complété très rapidement si votre code recherche des masques qui peuvent être combinés. Si votre code le fait, supprimez toutes les autres lignes (il ne/^2*02*$/
reste donc que les cas). Je ne pense pas que ce cas puisse être optimisé.rubis, assez rapide, mais cela dépend de l'entrée
Accélérez maintenant d'un facteur 2 ~ 2,5 en passant des chaînes aux entiers.
Usage:
Par exemple.
Le nombre de correspondances pour un seul masque est facilement calculé par le coefficient binomial. Ainsi, par exemple, il
122020
faut 32
s remplis, 10
et 21
. Il existe doncnCr(3,2)=nCr(3,1)=3!/(2!*1!)=3
différentes chaînes binaires correspondant à ce masque.Une intersection entre n masques m_1, m_2, ... m_n est un masque q, de sorte qu'une chaîne binaire s ne correspond à q que si elle correspond à tous les masques m_i.
Si nous prenons deux masques m_1 et m_2, son intersection est facilement calculée. Définissez simplement m_1 [i] = m_2 [i] si m_1 [i] == 2. L'intersection entre
122020
et111222
est111020
:Les deux masques individuels sont appariés par 3 + 1 = 4 chaînes, le masque d'intersection est apparié par une chaîne, il y a donc 3 + 1-1 = 3 chaînes uniques correspondant à l'un ou aux deux masques.
J'appellerai N (m_1, m_2, ...) le nombre de chaînes correspondant à tous les m_i. En appliquant la même logique que ci-dessus, nous pouvons calculer le nombre de chaînes uniques correspondant à au moins un masque, donné par le principe d'exclusion d'inclusion et voir également ci-dessous, comme ceci:
Il existe de très nombreuses combinaisons de prises, disons 30 masques sur 200.
Donc, cette solution fait l'hypothèse qu'il n'y a pas beaucoup d'intersections d'ordre élevé des masques d'entrée, c'est-à-dire. la plupart des n-tuples de n> 2 masques n'auront aucune correspondance commune.
Utilisez le code ici, le code à ideone peut être obsolète.
J'ai ajouté une fonction
remove_duplicates
qui peut être utilisée pour prétraiter l'entrée et supprimer les masques dem_i
sorte que toutes les chaînes qui y correspondent correspondent également à un autre masquem_j
., Pour l'entrée actuelle, cela prend en fait plus de temps car il n'y a pas de tels masques (ou pas beaucoup) , la fonction n'est donc pas encore appliquée aux données dans le code ci-dessous.Code:
C'est ce qu'on appelle le principe d'exclusion de l'inclusion, mais avant que quelqu'un ne me le montre, j'avais ma propre preuve, alors voilà. Cependant, faire quelque chose vous fait du bien.
Considérons le cas de 2 masques, appelons ensuite
0
et1
, d'abord. Nous prenons chaque chaîne binaire équilibrée et la classons en fonction du ou des masques auxquels elle correspond.c0
est le nombre de ceux qui correspondent uniquement au masque0
,c1
le nombre de ceux qui correspondent uniquement1
,c01
ceux qui correspondent au masque0
et1
.Soit
s0
la somme numérique du nombre de correspondances pour chaque masque (elles peuvent se chevaucher). Soits1
la somme du nombre de correspondances pour chaque paire (2 combinaisons) de masques. Soits_i
la somme du nombre de correspondances pour chaque (i + 1) combinaison de masques. Le nombre de correspondances de n-masques est le nombre de chaînes binaires correspondant à tous les masques.S'il y a n masques, la sortie souhaitée est la somme de tous
c
, c'est-à-dire.c = c0+...+cn+c01+c02+...+c(n-2)(n-1)+c012+...+c(n-3)(n-2)(n-1)+...+c0123...(n-2)(n-1)
. Ce que le programme calcule est la somme alternée de touss
, c'est-à-dire.s = s_0-s_1+s_2-+...+-s_(n-1)
. Nous voulons le prouvers==c
.n = 1 est évident. Considérons n = 2. Compter toutes les correspondances de mask
0
donnec0+c01
(le nombre de chaînes ne correspondant qu'à 0 + celles correspondant à la fois à0
et1
), compter toutes les correspondances de1
donnec1+c02
. Nous pouvons illustrer cela comme suit:Par définition,
s0 = c0 + c1 + c12
.s1
est le nombre total de correspondances de chaque combinaison de 2[0,1]
, c'est-à-dire. tous uniqyec_ij
s. Gardez cela à l'espritc01=c10
.Ainsi
s=c
pour n = 2.Considérons maintenant n = 3.
Ainsi
s=c
pour n = 3.c__i
représente le de tous lesc
s avec (i + 1) indices, par exemplec__1 = c01
pour n = 2 etc__1 = c01 + c02 + c12
pour n == 3.Pour n = 4, un modèle commence à émerger:
Ainsi
s==c
pour n = 4.En général, nous obtenons des coefficients binomiaux comme celui-ci (↓ est i, → est j):
Pour voir cela, considérez cela pour certains
i
etj
, il y a:Comme cela peut sembler déroutant, voici la définition appliquée à un exemple. Pour i = 1, j = 2, n = 4, cela ressemble à ceci (cf. ci-dessus):
Donc ici x = 6 (01, 02, 03, 12, 13, 23), y = 2 (deux c avec trois indices pour chaque combinaison), z = 4 (c012, c013, c023, c123).
Au total, il y a des
x*y
coefficientsc
avec des indices (j + 1), et il y en az
différents, donc chacun se produitx*y/z
fois, que nous appelons le coefficientk_ij
. Par simple algèbre, on obtientk_ij = ncr(n,i+1) ncr(n-i-1,j-i) / ncr(n,j+1) = ncr(j+1,i+1)
.Donc, l'indice est donné par
k_ij = nCr(j+1,i+1)
Si vous vous souvenez de toutes les définitions, tout ce que nous devons montrer est que la somme alternée de chaque colonne donne 1.La somme alternée
s0 - s1 + s2 - s3 +- ... +- s(n-1)
peut ainsi s'exprimer comme:Ainsi
s=c
pour tout n = 1,2,3, ...la source
0011 < 2211
,0022 < 0222
. Je pense que cela ne fait pas que les groupes soient plus grands2*n
, bien que ce soit encore trop grand dans le pire des cas.unifying two masks
le terme,union
cela a du sens pour moi et je peux le définir de cette façon, mais vous avez raison, dans l'intérêt de la compréhension mutuelle, je me suis fâché. @ Agawa001 Pouvez-vous être plus précis? De plus, si vous avez une bonne idée de rendre cela plus rapide, n'hésitez pas à utiliser les idées de cette réponse pour votre programme / réponse. Pour l'instant, il est assez rapide pour le grand cas de test, et s'il est multi-thread, il devrait prendre <0,1 s, ce qui est inférieur à toute mesure / comparaison significative, donc pour les cas de test plus difficiles sont nécessaires.C
Bonne chance pour obtenir la grande contribution à exécuter sur cela - il faudra probablement toute la nuit pour passer à travers environ. 60 ^ 30 permutations! Peut-être qu'un ensemble de données de taille intermédiaire pourrait être une bonne idée?
la source