#include <iostream>
#include <numeric>
#include <vector>
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);
// Get the first 10 partitions
for (int index = 1; index <= 10; ++index) {
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 << ".\n.\n.\n";
// Get the last 10 partitions
for (int index = totalNum - 9; index <= totalNum; ++index) {
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;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bnVtZXJpYz4KI2luY2x1ZGUgPHZlY3Rvcj4KCmludCBwQ291bnQoaW50IG4sIGludCBtLCBpbnQgbXlNYXgpIHsKCiAgICBpZiAobXlNYXggKiBtIDwgbikgcmV0dXJuIDA7CiAgICBpZiAobXlNYXggKiBtID09IG4pIHJldHVybiAxOwoKICAgIGlmIChtIDwgMikgcmV0dXJuIG07CiAgICBpZiAobiA8IG0pIHJldHVybiAwOwogICAgaWYgKG4gPD0gbSArIDEpIHJldHVybiAxOwoKICAgIGludCBuaXRlciA9IG4gLyBtOwogICAgaW50IGNvdW50ID0gMDsKCiAgICBmb3IgKDsgbml0ZXItLTsgbiAtPSBtLCAtLW15TWF4KSB7CiAgICAgICAgY291bnQgKz0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwogICAgfQoKICAgIHJldHVybiBjb3VudDsKfQoKc3RkOjp2ZWN0b3I8aW50PiB1blJhbmsoaW50IG4sIGludCBtLCBpbnQgbXlNYXgsIGludCBudGgpIHsKCiAgICBzdGQ6OnZlY3RvcjxpbnQ+IHoobSwgMCk7CiAgICBpbnQgY291bnQgPSAwOwogICAgaW50IGogPSAwOwoKICAgIGZvciAoaW50IGkgPSAwOyBpIDwgei5zaXplKCk7ICsraSkgewogICAgICAgIGludCB0ZW1wID0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwoKICAgICAgICBmb3IgKGludCByID0gbiAtIG0sIGsgPSBteU1heCAtIDE7CiAgICAgICAgICAgICAoY291bnQgKyB0ZW1wKSA8IG50aCAmJiByID4gMCAmJiBrOyByIC09IG0sIC0taykgewoKICAgICAgICAgICAgY291bnQgKz0gdGVtcDsKICAgICAgICAgICAgbiA9IHI7CiAgICAgICAgICAgIG15TWF4ID0gazsKICAgICAgICAgICAgKytqOwogICAgICAgICAgICB0ZW1wID0gcENvdW50KG4gLSAxLCBtIC0gMSwgbXlNYXgpOwogICAgICAgIH0KCiAgICAgICAgLS1tOwogICAgICAgIC0tbjsKICAgICAgICB6W2ldID0gajsKICAgIH0KCiAgICByZXR1cm4gejsKfQoKaW50IG1haW4oKSB7CglpbnQgbWF4ID0gMTA7CglpbnQgbWluID0gMzsKCWludCBOID0gNzsKCWludCBzdW0gPSA0MjsKCQogICAgaW50IG0gPSBOOwogICAgaW50IG4gPSBzdW0gLSBtICogKG1pbiAtIDEpOwogICAgaW50IG15TWF4ID0gbWF4IC0gbWluICsgMTsKICAgIGludCB0b3RhbE51bSA9IHBDb3VudChuLCBtLCBteU1heCk7CiAgICAKICAgIHN0ZDo6dmVjdG9yPGludD4gdihtYXggLSBtaW4gKyAxKTsKICAgIHN0ZDo6aW90YSh2LmJlZ2luKCksIHYuZW5kKCksIG1pbik7CiAgICAKICAgIC8vIEdldCB0aGUgZmlyc3QgMTAgcGFydGl0aW9ucwogICAgZm9yIChpbnQgaW5kZXggPSAxOyBpbmRleCA8PSAxMDsgKytpbmRleCkgewoJICAgIHN0ZDo6dmVjdG9yPGludD4geiA9IHVuUmFuayhuLCBtLCBteU1heCwgaW5kZXgpOwoJICAgIHN0ZDo6Y291dCA8PCBpbmRleCA8PCAiOiAiOwoJICAgIAoJICAgIGZvciAoaW50IGkgPSAwOyBpIDwgbTsgKytpKQoJICAgICAgICBzdGQ6OmNvdXQgPDwgdlt6W2ldXSA8PCAiICI7CgkgICAgICAgIAoJICAgIHN0ZDo6Y291dCA8PCAiXG4iOwoJfQoJCglzdGQ6OmNvdXQgPDwgIi5cbi5cbi5cbiI7CgkKCS8vIEdldCB0aGUgbGFzdCAxMCBwYXJ0aXRpb25zCglmb3IgKGludCBpbmRleCA9IHRvdGFsTnVtIC0gOTsgaW5kZXggPD0gdG90YWxOdW07ICsraW5kZXgpIHsKCSAgICBzdGQ6OnZlY3RvcjxpbnQ+IHogPSB1blJhbmsobiwgbSwgbXlNYXgsIGluZGV4KTsKCSAgICBzdGQ6OmNvdXQgPDwgaW5kZXggPDwgIjogIjsKCSAgICAKCSAgICBmb3IgKGludCBpID0gMDsgaSA8IG07ICsraSkKCSAgICAgICAgc3RkOjpjb3V0IDw8IHZbeltpXV0gPDwgIiAiOwoJICAgICAgICAKCSAgICBzdGQ6OmNvdXQgPDwgIlxuIjsKCX0KCQogICAgc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKICAgIHJldHVybiAwOwp9