Mon problème. Compte tenu de , je veux compter le nombre de multijeux valide S . Un multiset S est valide si
- La somme des éléments de est n , et
- Chaque numéro de à n peut être exprimée de manière unique comme une somme de quelques - uns des éléments de S .
Exemple. Par exemple , si alors { 1 , 1 , 1 , 1 , 1 } , { 1 , 2 , 2 } , { 1 , 1 , 3 } sont valides.
Cependant, n'est pas valide car 2 peut être formé à la fois par { 1 , 1 } et { 2 } (c'est-à-dire que 2 peut être exprimé comme 2 = 1 + 1 et 2 = 2 ) , donc la deuxième condition ne tient pas. De même 3 peut être formé par { 2 , 1 } et { 1 , 1 , 1 } .
} est également invalide car tous les nombres de 1 à 5 peuvent être créés de manière unique, mais la somme des éléments de S n'est pas 5 .
J'ai essayé de trouver un bon algorithme pour ce problème depuis un certain temps, mais je ne peux pas le résoudre. C'est du codechef . J'ai vu certaines des solutions soumises, mais je n'ai toujours pas pu obtenir la logique pour résoudre le problème. REMARQUE: la limite de temps pour la question est de 10 secondes et
Pour un multiset j'utiliserai la notation a i < si i < j , ce qui signifie qu'un i se produit c i fois en multiset S.
Jusqu'à présent, j'ai tiré quelques conclusions
- Le premier élément du multiset trié requis doit être
- Soit soit un ensemble suivant les deux propriétés alors ∀ r < k a r + 1 = a r ou (
- Soit , où a i se produit fois, suit les propriétés requises, puis de la conclusion ci-dessus nous pouvons dire que ∀ i a i | n + 1 et si j > i .
Preuve: a i + 1 = ( a i c i + a i - 1 ) + 1 ⇒ a i | a i + 1
- Considérons maintenant c'est-à-dire tous les les nombres suivants après 1 seront un multiple de d . Soit donc f ( n )être le compte d'un tel multiset possible alors où je suis sommant sur tout nombre possible de1's(=d-1). En d'autres termes,f(n-1)=g(n)=
Enfin mon problème est réduit à ceci - trouver d'une manière efficace afin qu'il ne dépasse pas la limite de temps.
la source
Réponses:
Voici ce que fait la solution la plus rapide . C'est en effet calculer votre fonction Étant donné n , nous le factorisons (voir ci-dessous), puis calculons tous les facteurs (voir ci-dessous) f 1 , … , f m dans un ordre tel que f i | f j implique i ≤ j (propriété P). Nous calculons maintenant g selon la formule en passant en revue les facteurs dans l'ordre donné. La propriété P garantit que lorsque nous calculons g ( d ) , nous avons déjà calculé g ( e ) pour tous les facteurs non triviaux e
Plus en détail, nous passons en revue les facteurs dans l'ordre, et pour chaque facteur , nous trouvons tous ses facteurs non triviaux en vérifiant lequel de f 1 , … , f i - 1 divise f i .fi f1,…,fi−1 fi
Affacturage: prétraitement: nous faisons une liste de tous les nombres premiers inférieurs à utilisant le tamis Eratosthène. Étant donné n , nous utilisons simplement la division d'essai.109 n
Générer tous les facteurs: cela se fait de manière récursive. Supposons que . Nous exécutons t boucles imbriquées l 1 ∈ { 0 , … , k 1 } , … , l t ∈ { 0 , … , k t } , et sortons p l 1 1 ⋯ p l tn=pk11⋯pktt t l1∈{0,…,k1},…,lt∈{0,…,kt} . Vous pouvez prouver la propriété P par induction.pl11⋯pltt
Optimisation: le programme étant exécuté sur plusieurs entrées, nous pouvons utiliser la mémorisation pour gagner du temps sur différentes entrées. Nous ne mémorisons que de petites valeurs (jusqu'à ), ce qui nous permet de stocker toutes les valeurs mémorisées dans un tableau. Le tableau est initialisé avec des zéros, et ainsi nous pouvons dire quelles valeurs sont déjà connues (puisque toutes les valeurs calculées sont positives).105
Si la factorisation première de est p k 1 1 , … , p k t t , alors f ( n ) ne dépend que de ( k 1 , … , k t ) , et en fait uniquement de la version triée de ce vecteur . Chaque nombre inférieur à 10 9 a au plus 29 facteurs premiers (avec répétition), et puisque p ( 29 ) = 4565 , il semble possible de calculer fn+1 pk11,…,pktt f(n) (k1,…,kt) 109 29 p(29)=4565 f (ou plutôt ) pour tous, récursivement. Cette solution pourrait être plus rapide s'il y avait de nombreuses entrées différentes; en l'état, il y en a au maximum 10 .g 10
Il est également possible que cette fonction, mappant les partitions au correspondant , ait une forme analytique explicite. Par exemple, g ( p k ) = 2 k - 1 , g ( p 1 … p t ) est donné par A000670 , et g ( p 2 1 p 2 … p t ) est donné par A005649 oug g(pk)=2k−1 g(p1…pt) g(p21p2…pt) A172109 .
la source
OK, vous avez donc une relation de récurrence pour (voir la fin de votre question).g(⋅)
À ce stade, il semble qu'une approche naturelle serait d'écrire l'algorithme récursif pour calculer et d'appliquer la mémorisation afin de ne pas calculer g ( i ) plus d'une fois. En d'autres termes, lorsque vous calculez g ( i ) , vous le stockez dans une table de hachage qui mappe i ↦ g ( i ) ; si vous avez besoin de connaître g ( i )g(n) g(i) g(i) i↦g(i) g(i) à l'avenir, vous pouvez le rechercher dans la table de hachage.
la source
Voici un indice pour vous aider à démarrer. Appliquer des algorithmes de programmation dynamique standard pour énumérer l'ensemble des partitions d'un entier et ajouter une logique pour vérifier laquelle permet une modification unique en vérifiant de manière itérative toutes les sommes, en effectuant des modifications et en vérifiant l'unicité.
Voici une approche qui sera probablement meilleure.
Cela devrait être assez faisable. Bonne chance! S'amuser! Travailler à travers les détails sera un bon exercice d'apprentissage en programmation dynamique.
la source