Réduction d'une boucle

Résolu/Fermé
Ryuku Messages postés 112 Date d'inscription jeudi 11 décembre 2008 Statut Membre Dernière intervention 2 novembre 2012 - 27 juin 2009 à 22:17
Ryuku Messages postés 112 Date d'inscription jeudi 11 décembre 2008 Statut Membre Dernière intervention 2 novembre 2012 - 28 juin 2009 à 20:08
Bonjour,

Voici mon problème :
soit nCk = n!/k!(n-k)! le nombre de combinaisons sans répétition.

je cherche tous les (n, k) qui vérifient nCk = a où a une constante donnée.

Moi j'ai fait une boucle pour les n de 0 à a qui contient une boucle de 0 à n pour les k :
si nCk = a alors je sauvegarde (n,k).

Moi je cherche une méthode plus rapide.

3 réponses

xmoix Messages postés 36 Date d'inscription vendredi 26 juin 2009 Statut Membre Dernière intervention 29 juin 2009 2
27 juin 2009 à 23:03
ah ! là... moi je suis pas matheux en tout cas, mais je peux toujours demander à mon prof d'info, lui il sait tout ce qui ressort des math ^^.
0
Ryuku Messages postés 112 Date d'inscription jeudi 11 décembre 2008 Statut Membre Dernière intervention 2 novembre 2012 24
28 juin 2009 à 19:55
Merci pour votre réponse, mais j'ai trouvé une solution.
0
KX Messages postés 16755 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 12 février 2025 3 020
27 juin 2009 à 23:10
Je pense qu'un petit rappel de théorie mathématiques s'impose...
Une propriété intéressante pour ton problème : k parmi n = (n-k) parmi n

On peut donc envisager de refaire une boucle mais en allant que jusqu'à n/2 puisqu'au delà on se retrouve à refaire les mêmes calculs (inutilement)

Après je ne sais pas en quel langage tu codes, mais l'idéal est d'utiliser des accumulateurs pour ne pas recalculer les factorielles à chaque fois...

Exemple en Pascal (je peux aussi te le faire en C/C++ ou Caml) :
function Recherche(a,n:integer):integer; // renvoie -1 si échec
var k,x,y,z:integer; // x=n! y=k! z=(n-k)!
begin
     
     // cas particuliers

     if a<1 then begin
                 result:= -1;
                 exit;
                 end;

     if a=1 then begin
                 result:=0;
                 exit;
                 end;

     // calcul de n!

     x:=1;
     for k:=2 to n do
         x:=x*k;

     // calcul des (k|n)

     y:=1;
     z:=x;

     for k:=1 to (n div 2) do
     begin
         y:=y*k;
         z:=z div k;

         if a*y*z=x then begin
                         result:=k;
                         exit;
                         end;
     end;

     // résultat par défaut

     result:= -1;
end;
0
Ryuku Messages postés 112 Date d'inscription jeudi 11 décembre 2008 Statut Membre Dernière intervention 2 novembre 2012 24
28 juin 2009 à 20:08
Salut,
Vous avez raison en ce qui concerne la réduction de la boucle à n/2 itérations mais en réfléchissant bien j'ai trouvé cette solution (En Pascal Delphi) :

function CmbPsbles(A : integer) : string; // Combinaisons possibles qui donnent A, résultat sous chaîne de caractères


var N, K : integer;
begin // pour A = 1 il existe une infinité de combinaisons.
if A = 2 then // pour A = 2 le seul résultat est 2C1
Result := '2C1|'
else
begin
Result := '';
N := 2;
while nCk(N, 2) <= A do // on cherche
inc(N); // le N qui vérifie nC2 <= A, car si ce N existe il ne doit satisfaire cette condition (preuve par le triangle de Pascal.
dec(N); // revenir de 1 car on s'est arrêté à N + 1.
if N <> A then // le cas de N = A est traité seul
begin
for K := 2 to N do // On cherche
if nCk(N, K) = A then // le premier K qui vérifie
break; // nCk = A
if K < N then // pour vérifier que le N et le K existent réellement.
begin
Result := Result + IntToStr(N) + 'C' + IntToStr(K) + '|'; // le résultat nCk
if K <> N / 2 then // si le K est égal vraiment à n / 2 alors on fait pas nCn-k
Result := Result + IntToStr(N) + 'C' + IntToStr(N - K) + '|' // le résultat nCn-k
end
end;
Result := Result + IntToStr(A) + 'C1|' + IntToStr(A) + 'C' + IntToStr(A - 1) + '|' // le cas de N = A donc le résultat est AC1 et ACA-1
end
end;

Merci.
0