L'analyse du problème P7118 nous plonge dans un univers où les "Galgame" (représentés par des arbres binaires) sont classés selon leur "attractivité". L'objectif est de déterminer, pour un Galgame donné, combien d'autres Galgame "essentiellement différents" sont considérés comme moins attractifs.
1. Compréhension du Concept d'Attractivité
L'attractivité d'un Galgame est définie par le nombre de Galgame qui le précèdent dans un ordre spécifique. La règle de comparaison entre deux Galgame, G1 et G2, ressemble fortement à une comparaison lexicographique sur leurs structures d'arbres binaires :
- Comparaison par taille globale : Si le nombre total de scènes (nœuds de l'arbre) diffère, le Galgame avec plus de scènes est jugé plus attractif.
- Comparaison de la scène A (sous-arbre gauche) : Si les nombres de scènes sont identiques, on compare récursivement leurs scènes A. Le Galgame dont la scène A est plus attractive l'emporte.
- Comparaison de la scène B (sous-arbre droit) : Si les nombres de scènes sont identiques et que les scènes A sont "essentiellement identiques" (même structure et même attractivité), on compare récursievment leurs scènes B. Le Galgame dont la scène B est plus attractive l'emporte.
Notre tâche est de compter les Galgame G' qui sont "moins attractifs" que notre Galgame cible G. Ces Galgame G' se répartissent en deux catégories principales :
- Catégorie 1 : Les Galgame
G'qui possèdent un nombre de scènes inférieur à celui deG. - Catégorie 2 : Les Galgame
G'qui ont le même nombre de scènes queG, mais qui sont jugés moins attractifs selon les règles 2 ou 3.
La solution consiste à calculer la somme des Galgame de ces deux catégories.
2. Catégorie 1 : Comptage des Galgame avec moins de nœuds
Cette partie du problème relève de la combinatoire pure. Un Galgame avec i scènes est un arbre binaire enraciné avec i nœuds. Le nombre d'arbres binaires enracinés "essentiellement différents" (c'est-à-dire de formes distinctes) avec i nœuds est donné par le i-ème nombre de Catalan, noté \(C_i\).
Les Nombres de Catalan
Les nombres de Catalan sont omniprésents en combinatoire et apparaissent dans de nombreux problèmes (séquences de parenthèses bien formées, chemins de Dyck, triangulations de polygones, etc.). Leur formule générale est \(C_n = \frac{1}{n+1}\binom{2n}{n}\), et ils peuvent être calculés récursivement par \(C_0=1, C_{n+1} = \sum_{i=0}^{n}C_i C_{n-i}\). En pratique, pour la programmation, on précalcule souvent les factorielles et leurs inverses modulaires pour calculer les coefficients binomiaux.
Si notre Galgame G possède n scènes, le nombre de Galgame de la première catégorie est la somme des nombres de Catalan pour tous les nombres de nœuds inférieurs à n :
\[ \text{Nombre de Galgame de Catégorie 1} = \sum_{i=0}^{n-1} C_i \] Il est important de noter que le cas de 0 nœuds (l'arbre vide) est inclus, correspondant à \(C_0=1\).
Nous pouvons précalculer tous les nombres de Catalan nécessaires jusqu'à n-1 et en déduire cette somme en temps \(O(n)\).
3. Catégorie 2 : Comptage des Galgame avec un nombre de nœuds identique
C'est la partie la plus complexe du problème. Nous devons trouver combien de Galgame G' ont n nœuds (comme G) mais sont moins attractifs. Nous utilisons une fonction récursive, que nous nommerons compterMoinsAttractifs(noeud_courant, multiplicateur), pour effectuer ce calcul.
Cette fonction calcule le nombre de Galgame qui ont la même taille que le sous-arbre enraciné en noeud_courant, mais qui sont moins attractifs que ce sous-arbre. Le paramètre multiplicateur représente le nombre de façons dont ce sous-problème a pu être atteint depuis la racine de G.
Logique de compterMoinsAttractifs(noeud_o, facteur_contexte) :
Supposons que le sous-arbre en noeud_o ait une taille totale S. Ses enfants gauche (scène A) et droit (scène B) sont enfant_gauche[noeud_o] et enfant_droit[noeud_o], avec des tailles respectives S_A et S_B. Il est évident que \(S = 1 + S_A + S_B\).
-
**Cas 1 : La scène A de
G'est plus petite que celle deG.**Nous cherchons un GalgameG'de tailleSdont le sous-arbre gauche (G'_A) ainœuds, où \(0 \le i < S_A\).- Pour chaque
i, il existe \(C_i\) formes possibles pourG'_A. - Le sous-arbre droit (
G'_B) doit alors avoir \(S - 1 - i\) nœuds. Il existe \(C_{S-1-i}\) formes possibles pourG'_B. - Le nombre de Galgame
G'pour unidonné est donc \(C_i \times C_{S-1-i}\).
Nous sommons ces contributions pour toutes les valeurs de
i:// Contribution du cas 1 : le sous-arbre gauche de G' est plus petit que celui de G long long total_inf = 0; for (int i = 0; i < taille_sous_arbre[enfant_gauche[noeud_o]]; ++i) { total_inf = (total_inf + catalan[i] * catalan[taille_sous_arbre[noeud_o] - 1 - i]) % MODULO; } resultat_global = (resultat_global + facteur_contexte * total_inf) % MODULO; - Pour chaque
-
**Cas 2 : La scène A de
G'a la même taille que celle deG, mais est intrinsèquement moins attractive.**Ici,G'_Aa \(S_A\) nœuds, etG'_Ba \(S_B\) nœuds.G'_Aest moins attractif queG_A. Le nombre de tellesG'_Aest exactement ce quecompterMoinsAttractifs(enfant_gauche[noeud_o], ...)calcule. Pour chaque telG'_A, le sous-arbre droitG'_Bpeut être n'importe quelle des \(C_{S_B}\) formes possibles d'un arbre à \(S_B\) nœuds.// Contribution du cas 2 : G'_A a même taille, mais est moins attractif if (enfant_gauche[noeud_o] != 0) { // S'il existe un enfant gauche long long nouveau_facteur = (facteur_contexte * catalan[taille_sous_arbre[enfant_droit[noeud_o]]]) % MODULO; compterMoinsAttractifs(enfant_gauche[noeud_o], nouveau_facteur); } -
**Cas 3 : La scène A de
G'est essentiellement identique à celle deG, mais la scène B deG'est moins attractive.**Dans ce cas,G'_Aest identique àG_A(1 seule possibilité). Nous devons alors comparerG'_BetG_B. Le nombre deG'_Bmoins attractifs queG_Best calculé parcompterMoinsAttractifs(enfant_droit[noeud_o], ...).// Contribution du cas 3 : G'_A est identique, G'_B est moins attractif if (enfant_droit[noeud_o] != 0) { // S'il existe un enfant droit compterMoinsAttractifs(enfant_droit[noeud_o], facteur_contexte); // Le facteur_contexte reste inchangé }
4. Optimisation \(O(N^2)\) vers \(O(N \log N)\) : La Fusion Heuristique
L'algorithme de compterMoinsAttractifs décrit ci-dessus peut avoir une complexité en \(O(N^2)\) dans le pire des cas (par exemple, un arbre dégénéré en liste) à cause de la boucle du Cas 1. Cette boucle itère \(S_A\) fois.
L'optimisation réside dans l'utilisation d'une identité des nombres de Catalan :
\[ \sum_{i=0}^{K} C_i \cdot C_{K-i} = C_{K+1} \] Dans notre Cas 1, la somme est \(\sum_{i=0}^{S_A-1} C_i \cdot C_{S-1-i}\). Posons \(K = S-1\). Nous savons que \(\sum_{i=0}^{S-1} C_i \cdot C_{S-1-i} = C_S\). Nous pouvons donc réécrire notre somme comme suit :
\[ \sum_{i=0}^{S_A-1} C_i \cdot C_{S-1-i} = C_S - \sum_{i=S_A}^{S-1} C_i \cdot C_{S-1-i} \] La nouvelle somme \(\sum_{i=S_A}^{S-1} C_i \cdot C_{S-1-i}\) itère \( (S-1) - S_A + 1 = S_B + 1 \) fois.
Nous avons donc deux manières de calculer la somme du Cas 1 :
- Directement, en itérant \(S_A\) fois.
- Indirectement, en soustrayant une somme qui itère \(S_B + 1\) fois de \(C_S\).
L'idée de la fusion heuristique est de toujours choisir la méthode qui implique le moins d'itérations. Autrement dit :
- Si \(S_A \le S_B + 1\), on utilise la première méthode (boucle sur \(S_A\)).
- Si \(S_A > S_B + 1\), on utilise la deuxième méthode (boucle sur \(S_B + 1\)).
En choisissant toujours de parcourir le sous-arbre de plus petite taille (ou l'un des deux côtés si la différence est faible), la profondeur effective des appels récursifs pour un nœud donné est bornée par \(O(\log N)\). Cela réduit la complexité totale de l'algorithme à \(O(N \log N)\).
5. Étapes de Résolution Complètes
- Précalculs : Calculer les factorielles, inverses modulaires, et enfin tous les nombres de Catalan \(C_0, \dots, C_n\) modulo \(998244353\).
- Calcul de la taille des sous-arbres : Effectuer un parcours en profondeur (DFS) initial pour déterminer la taille de chaque sous-arbre
taille_sous_arbre[i]. - Calcul des Galgame de Catégorie 1 : Sommer les nombres de Catalan de \(C_0\) à \(C_{n-1}\).
- Calcul des Galgame de Catégorie 2 : Appeler la fonction récursive optimisée
compterMoinsAttractifs(racine_de_G, 1). - Résultat Final : Additionner les résultats des étapes 3 et 4, en s'assurant que toutes les opérations respectent l'arithmétique modulaire.