Partage
  • Partager sur Facebook
  • Partager sur Twitter

Boîtes factorielles

Boîtes factorielles france IOI

17 septembre 2020 à 17:58:39

Bonjour à tous 

est ce que quelqu'un peut juste me donner une indication comment je peux definir une faction qui pour toute n réel naturel ,donne un entier naturel  "i" tel tel que n >= max(fact(i) , je crois c'est ca qui manque dans mon code , sinon vous avez des idées pour me guidez , ... Merci d'avance 

Un marchand de légumes très maniaque souhaite ranger ses petits pois en les regroupant en boîtes de telle sorte que chaque boîte contienne un nombre factoriel de petits pois. On rappelle qu'un nombre est factoriel s'il est de la forme 1, 1 x 2, 1 x 2 x 3, 1 x 2 x 3 x 4... et qu'on les note sous la forme suivante :

n!=1×2×3××(n1)×nn!=1×2×3×…×(n−1)×n

Il souhaite également utiliser le plus petit nombre de boîtes possible.

Ainsi, s'il a 17 petits pois, il utilisera :

  • 2 boîtes de 3! = 6 petits pois
  • 2 boîtes de 2! = 2 petits pois
  • 1 boîte de 1! = 1 petits pois
ce qui donne bien 2 x 3! + 2 x 2! + 1 x 1! = 12 + 4 + 1 = 17.

D'une manière générale, s'il a nbPetitsPois, il doit trouver une suite a1,a2,,apa1,a2,…,ap d'entiers positifs ou nuls avec ap>0ap>0 et telle que :

nbPetitsPois=a1×1!+a2×2!++ap×p!nbPetitsPois=a1×1!+a2×2!+…+ap×p!
avec a1++apa1+…+ap minimal.

Limites de temps et de mémoire (Python)

  • Temps : 0,5 s sur une machine à 1 GHz.
  • Mémoire : 8 000 ko.

Contraintes

1<= nbPetitsPois <= 500 000 000

Entrée

Un unique entier, nbPetitsPois le nombre total de petits poids.

Sortie

  • Sur le première ligne, l'entier p
  • Sur la seconde ligne, les entiers a1,a2,,apa1,a2,…,ap

Exemple

entrée :

17

sortie :

3
1 2 2
nombre = int(input()) 
L=[] 
somme = 0
fonction(nombre)
for k in range(i)
    Reste = (nombre % fact(k))
    diviseur = (nombre // fact(k))
    while fact(k) >= 2:
        Reste = (Reste % fact(k-1))
        diviseur = (diviseur // fact(k-1))
        somme = somme + 1 
        valeurs = (diviseur-Reste)/fact(k)
        L.append(valeurs)

-
Edité par HuyouHuyou 17 septembre 2020 à 17:59:51

  • Partager sur Facebook
  • Partager sur Twitter
17 septembre 2020 à 18:58:03

bah ça peut être simple, tu fais une boucle 

from math import factorial as fact # pour être complet (et ne pas refaire la fonction fact qui en soit n'est pas compliqué))
max=1
i=0
while max < nombre:
    i=i+1
    max=fact(i)

print(f"le nombre {i} donne la valeur {max} qui est la plus proche de {nombre}")



-
Edité par umfred 17 septembre 2020 à 19:01:17

  • Partager sur Facebook
  • Partager sur Twitter
17 septembre 2020 à 19:26:36

La stratégie est de trouver d'abord le nombre k le plus grand tel que fact(k) <= nombre
ensuite on le soustrait de nombre autant de fois qu'on peut
et on recommence avec le nombre résiduel.
Je pense que ça pourrait même être récursif.
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

17 septembre 2020 à 20:14:20

C'est un exercice marrant, la 1ere chose a regarder c'est:

1<= nbPetitsPois <= 500 000 000

Cela signifie que la plus grosse boite est de 12!

Maintenant comme l'explique PierrotLeFou, il faut juste aller de la plus grosse a la plus petite boite et regarder si n > boite et si oui de quel facteur.

Une optimisation est de stocker une fois pour toute les factorielles pour eviter de le recalculer a chaque fois dans une liste ou alors juste calculer fact(12) et la décrémenter à chaque fois. On arrive au code suivant:

from math import factorial

def foo(n):
    box_content = factorial(12)
    box_size = 12
    ans = []
    while True:
        if box_content < n:
            j = n // box_content
            ans.append((box_size, j))
            n %= box_content

        if n == 0:
            return ans
        
        box_content //= box_size  # to not recompute the previous factorial
        box_size -= 1

print(foo(100))
  • Partager sur Facebook
  • Partager sur Twitter
18 septembre 2020 à 0:57:46

Il n'est pas vraiment nécessaire de calculer toutes les factorielles à l'avance.
Ce code simpliste est suffisamment efficace:
-
L = []
n = int(input("Nombre: "))
if not 1 <= n <= 500000000:
    print("Nombre hors limites")
    exit()
#
k = 1
f = 1
while f < n:
    k += 1
    f *= k
#
p = 0
while n > 0:
    while f > n:
        f //= k
        k -= 1
    c = n // f
    p += c
    L.append(f"{c}*{k}!")
    n %= f
#
print("p=",p)
print(" + ".join(L))
-
Oups! je n'ai pas lu correctement, je donne le nombre total d'éléments, pas le nombre de boîtes. On devrait lire:
print("p=", len(L))

-
Edité par PierrotLeFou 18 septembre 2020 à 2:04:04

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

18 septembre 2020 à 3:48:02

Bonjour, 

Quelqu'un peut m'aider à trouver une solution, je voudrais afficher le resultat dans l'interface tkinter sachant que je dois utiliser les listes pour les calculs. Est-il possible de se passer du console lors de la saisie des données? 

Merci d'avance.

                             

-
Edité par MohamedAliBenAissa 18 septembre 2020 à 4:12:28

  • Partager sur Facebook
  • Partager sur Twitter
18 septembre 2020 à 5:33:18

MohamedAliBenAissa a écrit:

Bonjour, 

Quelqu'un peut m'aider à trouver une solution, je voudrais afficher le resultat dans l'interface tkinter sachant que je dois utiliser les listes pour les calculs. Est-il possible de se passer du console lors de la saisie des données? 

Merci d'avance.

Crée ton propre sujet ...

-
Edité par MohamedAliBenAissa il y a environ 1 heure



  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

18 septembre 2020 à 11:04:53

@Mohamed  créée ton propre sujet stp.

Sinon pour l'exo, je crois que j'ai bien opti.

P = int(input())

res = []
n = fac = 1
while P:
    fac *= n
    mod = P % (fac * (n + 1))
    res.append(mod // fac)
    P -= mod
    n += 1

print(len(res))
print(*res)



  • Partager sur Facebook
  • Partager sur Twitter
18 septembre 2020 à 16:56:42

@thelinekioubeur:
As-tu testé ton code avec 18? J'obtien:
3
0 0 3
Avec 18, on n'a qu'une seule boîte de 3 fois 3!
Pour 600:
Avec ton code:
5                                                                                                                       
0 0 0 0 5                                                                                                               
         Avec mon code:                                                                                                               
p= 1                                                                                                                    
5*5!                                                                                                                     
Pour 12! = 479001600:
12
0 0 0 0 0 0 0 0 0 0 0 1

-
Edité par PierrotLeFou 18 septembre 2020 à 17:38:18

  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

19 septembre 2020 à 15:14:04

@pierrot  avec 18 on a 3 boîtes de 3! chacune.

Donc sur la première ligne je met 3 (car la plus grande boîte est de taille 3!)

J'ai testé le code sur france ioi, il passe.

  • Partager sur Facebook
  • Partager sur Twitter
20 septembre 2020 à 2:36:56

Voici ce que l'exemple donnait:
entrée :
17
sortie :
3
1 2 2
De toute façon, on sais tous deux comment faire. :)
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.

20 septembre 2020 à 18:17:47

Oui, le 3 signifie que la plus grosse boîte est de taille 3! .

Et le "1 2 2" signifie une boîte de 1!, deux boîtes de 2! et deux boîtes de 3!

  • Partager sur Facebook
  • Partager sur Twitter
20 septembre 2020 à 18:43:01

Je trouve que l'énoncé du problème n'est pas clair, tu l'interprète d'une façon et moi d'une autre.
Dans l'exemple que j'ai testé avec ton code pour 12!, j'ai 11 0 avant le 1.
OK je sais compter jusqu'à 12 ..., mais je trouvais ma façon plus estétique (très subjectif)
mais ta méthode est plus efficace que la mienne.
  • Partager sur Facebook
  • Partager sur Twitter

Le Tout est souvent plus grand que la somme de ses parties.