Kombinatoryka - znajdywanie elementu

0

Witam

Mam ciekawy problem z którym nie mogę się już uporać jakiś dłuższy czas, mianowicie chodzi o kombinatorykę. Mam kombinacje bez powtórzeń czyli:

0,1,2,3,4 //index 0
0,1,2,3,5
0,1,2,3,6
0,1,2,3,7
0,1,2,3,8 //index 4
0,1,2,3,9
0,1,2,3,10
0,1,2,4,5
0,1,2,4,6
0,1,2,4,7 //index 9
..
aż do

6,7,8,9,10

Czyli bodajże C(n,k) czyli C(10,5)

Napisałem sobie funkcje która mi oblicza index na podstawie podanej kombinacji, czyli mojIndex = func(0,1,2,3,8)
mojIndex == 4

wszystko jest ok, ale teraz jak napisać funkcje odwrotna czyli taka, która po podaniu mi indeksu zwróci kombinacje ?
Czyli comb = func(4)
comb = {0,1,2,3,8}

??

Ma ktoś jakieś pomysły ?
Ktos gdzies mi poradzil zebym uzyl tego:

https://secure.wikimedia.org/wikipedia/en/wiki/Combinatorial_number_system#Example

Probowalem srednio mi to chodzilo i nie bardzo moge zrozumiec do konca ...

Czy ma ktos jakis pomysl?
Chodzi mi o rozwiazanie jak najszybsze najlepiej za pomoca dzialania matematycznego, bo moge to zrobic przeciez w petli sprawdzajac index ale to zbyt dlugo trwa (bede mial wiecej kombinacji), oczywiscie moze byc petla itd ale jak najmniej chodzi mi o wydajnosc

Z gory dziekuje za wszelka pomoc i sugestie
Pozdrawiam

0

Wymyśliłem coś takiego, musisz to przetestować by mieć pewność, że jest dobrze (indeksowanie kombinacji jest nieco inaczej, ale jeśli działa to powinieneś to dać radę zmienić):

vector<int> combinationNr(int combinationID, int n, int k)
{
    assert(n>=2 && k >0 && k <n);
    vector<int> result(k);

    int possibilities = n-k+1; // ile możliwych liczb zostało
    int currentNumber = 0;
    // n - bo tyle jest liczb, -(k-1) bo co najmniej tyle liczb musi zostać na pozostałe komórki

    for(int i=0; i<k; ++i) {
        assert(possibilities>0);
        int shift = combinationID % possibilities;
        combinationID = combinationID / possibilities;
        currentNumber += shift;
        result[i] = currentNumber++;
        possibilities -= shift; // tyle możliwości ubywa po wybraniu kolejnej liczby
        assert(currentNumber<n);
    }

    return result;
}
0

Dziekuje, rozwiazanie juz znalazlem na forum :-)

0

a skad sie wzielo numbersLeft ? nigdzie nie jest zadeklarowane... ta funkcja zwraca zawsze liczby w postaci: jesli podam id 120 to zwroci 120,121,122,123,124 itd

0

wołam (i, 5, 2)

   0 + 0 1 
   1 + 1 2 
   2 + 2 3 
   3 + 3 4   
   4 + 0 2 
   5 + 1 3 
   6 + 2 4 
   7 - 3 4    <- było
   8 + 0 3 
   9 + 1 4 
  10 - 2 3    <- było
  11 - 3 4    <- już było
  12 + 0 4    <-pierwsze 0 4
dalej już nie istotne
  13 - 1 2 
  14 - 2 4 
  15 - 3 4 
  16 - 0 1  

wolę

void n2p(int c, long long z, long long b, int n, int k){
        if(z<b) {
                putchar(c);
                if (n>0) n2p(c+1, z,   b*   k /n, n-1, k-1);
        } else  if (n>0) n2p(c+1, z-b, b*(n-k)/n, n-1, k  );}

1 użytkowników online, w tym zalogowanych: 0, gości: 1