#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;
}