#include <iostream>
#include <numeric>
#include <vector>
#include <random>
#include <algorithm>
int pCount(int n, int m, int myMax) {
if (myMax * m < n) return 0;
if (myMax * m == n) return 1;
if (m < 2) return m;
if (n < m) return 0;
if (n <= m + 1) return 1;
int niter = n / m;
int count = 0;
for (; niter--; n -= m, --myMax) {
count += pCount(n - 1, m - 1, myMax);
}
return count;
}
std::vector<int> unRank(int n, int m, int myMax, int nth) {
std::vector<int> z(m, 0);
int count = 0;
int j = 0;
for (int i = 0; i < z.size(); ++i) {
int temp = pCount(n - 1, m - 1, myMax);
for (int r = n - m, k = myMax - 1;
(count + temp) < nth && r > 0 && k; r -= m, --k) {
count += temp;
n = r;
myMax = k;
++j;
temp = pCount(n - 1, m - 1, myMax);
}
--m;
--n;
z[i] = j;
}
return z;
}
int main() {
int max = 10;
int min = 3;
int N = 7;
int sum = 42;
int m = N;
int n = sum - m * (min - 1);
int myMax = max - min + 1;
int totalNum = pCount(n, m, myMax);
std::vector<int> v(max - min + 1);
std::iota(v.begin(), v.end(), min);
std::vector<int> indexVec(totalNum);
std::random_device rd;
std::mt19937 gen(rd());
std::iota(indexVec.begin(), indexVec.end(), 1);
std::shuffle(indexVec.begin(), indexVec.end(), gen);
// random-sample without replacement
std::vector<int> randVec(indexVec.begin(), indexVec.begin() + 20);
for (auto index: randVec) {
std::vector<int> z = unRank(n, m, myMax, index);
std::cout << index << ": ";
for (int i = 0; i < m; ++i)
std::cout << v[z[i]] << " ";
std::cout << "\n";
}
std::cout << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bnVtZXJpYz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPHJhbmRvbT4KI2luY2x1ZGUgPGFsZ29yaXRobT4KCmludCBwQ291bnQoaW50IG4sIGludCBtLCBpbnQgbXlNYXgpIHsKCiAgICBpZiAobXlNYXggKiBtIDwgbikgcmV0dXJuIDA7CiAgICBpZiAobXlNYXggKiBtID09IG4pIHJldHVybiAxOwoKICAgIGlmIChtIDwgMikgcmV0dXJuIG07CiAgICBpZiAobiA8IG0pIHJldHVybiAwOwogICAgaWYgKG4gPD0gbSArIDEpIHJldHVybiAxOwoKICAgIGludCBuaXRlciA9IG4gLyBtOwogICAgaW50IGNvdW50ID0gMDsKCiAgICBmb3IgKDsgbml0ZXItLTsgbiAtPSBtLCAtLW15TWF4KSB7CiAgICAgICAgY291bnQgKz0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwogICAgfQoKICAgIHJldHVybiBjb3VudDsKfQoKc3RkOjp2ZWN0b3I8aW50PiB1blJhbmsoaW50IG4sIGludCBtLCBpbnQgbXlNYXgsIGludCBudGgpIHsKCiAgICBzdGQ6OnZlY3RvcjxpbnQ+IHoobSwgMCk7CiAgICBpbnQgY291bnQgPSAwOwogICAgaW50IGogPSAwOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgei5zaXplKCk7ICsraSkgewogICAgICAgIGludCB0ZW1wID0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwoKICAgICAgICBmb3IgKGludCByID0gbiAtIG0sIGsgPSBteU1heCAtIDE7CiAgICAgICAgICAgICAoY291bnQgKyB0ZW1wKSA8IG50aCAmJiByID4gMCAmJiBrOyByIC09IG0sIC0taykgewoKICAgICAgICAgICAgY291bnQgKz0gdGVtcDsKICAgICAgICAgICAgbiA9IHI7CiAgICAgICAgICAgIG15TWF4ID0gazsKICAgICAgICAgICAgKytqOwogICAgICAgICAgICB0ZW1wID0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwogICAgICAgIH0KCiAgICAgICAgLS1tOwogICAgICAgIC0tbjsKICAgICAgICB6W2ldID0gajsKICAgIH0KCiAgICByZXR1cm4gejsKfQoKaW50IG1haW4oKSB7CglpbnQgbWF4ID0gMTA7CglpbnQgbWluID0gMzsKCWludCBOID0gNzsKCWludCBzdW0gPSA0MjsKCQogICAgaW50IG0gPSBOOwogICAgaW50IG4gPSBzdW0gLSBtICogKG1pbiAtIDEpOwogICAgaW50IG15TWF4ID0gbWF4IC0gbWluICsgMTsKICAgIGludCB0b3RhbE51bSA9IHBDb3VudChuLCBtLCBteU1heCk7CiAgICAKICAgIHN0ZDo6dmVjdG9yPGludD4gdihtYXggLSBtaW4gKyAxKTsKICAgIHN0ZDo6aW90YSh2LmJlZ2luKCksIHYuZW5kKCksIG1pbik7CiAgICAKICAgIHN0ZDo6dmVjdG9yPGludD4gaW5kZXhWZWModG90YWxOdW0pOwogICAgc3RkOjpyYW5kb21fZGV2aWNlIHJkOwogICAgc3RkOjptdDE5OTM3IGdlbihyZCgpKTsKICAgIHN0ZDo6aW90YShpbmRleFZlYy5iZWdpbigpLCBpbmRleFZlYy5lbmQoKSwgMSk7CiAgICBzdGQ6OnNodWZmbGUoaW5kZXhWZWMuYmVnaW4oKSwgaW5kZXhWZWMuZW5kKCksIGdlbik7CgogICAgLy8gcmFuZG9tLXNhbXBsZSB3aXRob3V0IHJlcGxhY2VtZW50CiAgICBzdGQ6OnZlY3RvcjxpbnQ+IHJhbmRWZWMoaW5kZXhWZWMuYmVnaW4oKSwgaW5kZXhWZWMuYmVnaW4oKSArIDIwKTsKICAgIAogICAgZm9yIChhdXRvIGluZGV4OiByYW5kVmVjKSB7CgkgICAgc3RkOjp2ZWN0b3I8aW50PiB6ID0gdW5SYW5rKG4sIG0sIG15TWF4LCBpbmRleCk7CgkgICAgc3RkOjpjb3V0IDw8IGluZGV4IDw8ICI6ICI7CiAKCSAgICBmb3IgKGludCBpID0gMDsgaSA8IG07ICsraSkKCSAgICAgICAgc3RkOjpjb3V0IDw8IHZbeltpXV0gPDwgIiAiOwogCgkgICAgc3RkOjpjb3V0IDw8ICJcbiI7Cgl9CgkKICAgIHN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7CiAgICByZXR1cm4gMDsKfQ==