#include <iostream>
#include <cassert>
#include <vector>
// Permutations N threads.
int64_t f(std::vector<int64_t> nodes)
{
size_t N = nodes.size();
// In the case of 0 threads there is 1 permutation.
if (N == 0)
return 1;
// Each of the existing threads should have at least one node.
bool have_all_one_node = true;
std::vector<int64_t> v;
for (auto s : nodes)
{
if (s == 0)
have_all_one_node = false;
else
v.push_back(s);
}
if (!have_all_one_node)
return f(v);
// In the case of 1 thread, each node can only be connected
// to itself; so one permutation.
if (N == 1)
return 1;
// Otherwise we run over all possible ways the first
// node of the first thread can be connected and sum
// the results.
// Firstly, this node can be self-connected.
--v[0];
int64_t sum = f(v);
// Otherwise it is connected one of the remaining threads.
for (size_t i = 1; i < N; ++i)
{
--v[i];
sum += (v[i] + 1) * f(v);
++v[i];
}
return sum;
}
int main()
{
int number_of_threads;
int nodes_per_thread;
std::cin >> number_of_threads >> nodes_per_thread;
std::vector<int64_t> v(number_of_threads, nodes_per_thread);
std::cout << "#threads: " << number_of_threads << ", #nodes/thread: " << nodes_per_thread << ", permutations: " << f(v) << std::endl;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8Y2Fzc2VydD4KI2luY2x1ZGUgPHZlY3Rvcj4KCi8vIFBlcm11dGF0aW9ucyBOIHRocmVhZHMuCmludDY0X3QgZihzdGQ6OnZlY3RvcjxpbnQ2NF90PiBub2RlcykKewogIHNpemVfdCBOID0gbm9kZXMuc2l6ZSgpOwoKICAvLyBJbiB0aGUgY2FzZSBvZiAwIHRocmVhZHMgdGhlcmUgaXMgMSBwZXJtdXRhdGlvbi4KICBpZiAoTiA9PSAwKQogICAgcmV0dXJuIDE7CgogIC8vIEVhY2ggb2YgdGhlIGV4aXN0aW5nIHRocmVhZHMgc2hvdWxkIGhhdmUgYXQgbGVhc3Qgb25lIG5vZGUuCiAgYm9vbCBoYXZlX2FsbF9vbmVfbm9kZSA9IHRydWU7CiAgc3RkOjp2ZWN0b3I8aW50NjRfdD4gdjsKICBmb3IgKGF1dG8gcyA6IG5vZGVzKQogIHsKICAgIGlmIChzID09IDApCiAgICAgIGhhdmVfYWxsX29uZV9ub2RlID0gZmFsc2U7CiAgICBlbHNlCiAgICAgIHYucHVzaF9iYWNrKHMpOwogIH0KICBpZiAoIWhhdmVfYWxsX29uZV9ub2RlKQogICAgcmV0dXJuIGYodik7CgogIC8vIEluIHRoZSBjYXNlIG9mIDEgdGhyZWFkLCBlYWNoIG5vZGUgY2FuIG9ubHkgYmUgY29ubmVjdGVkCiAgLy8gdG8gaXRzZWxmOyBzbyBvbmUgcGVybXV0YXRpb24uCiAgaWYgKE4gPT0gMSkKICAgIHJldHVybiAxOwoKICAvLyBPdGhlcndpc2Ugd2UgcnVuIG92ZXIgYWxsIHBvc3NpYmxlIHdheXMgdGhlIGZpcnN0CiAgLy8gbm9kZSBvZiB0aGUgZmlyc3QgdGhyZWFkIGNhbiBiZSBjb25uZWN0ZWQgYW5kIHN1bQogIC8vIHRoZSByZXN1bHRzLgoKICAvLyBGaXJzdGx5LCB0aGlzIG5vZGUgY2FuIGJlIHNlbGYtY29ubmVjdGVkLgogIC0tdlswXTsKICBpbnQ2NF90IHN1bSA9IGYodik7CgogIC8vIE90aGVyd2lzZSBpdCBpcyBjb25uZWN0ZWQgb25lIG9mIHRoZSByZW1haW5pbmcgdGhyZWFkcy4KICBmb3IgKHNpemVfdCBpID0gMTsgaSA8IE47ICsraSkKICB7CiAgICAtLXZbaV07CiAgICBzdW0gKz0gKHZbaV0gKyAxKSAqIGYodik7CiAgICArK3ZbaV07CiAgfQoKICByZXR1cm4gc3VtOwp9CgppbnQgbWFpbigpCnsKICBpbnQgbnVtYmVyX29mX3RocmVhZHM7CiAgaW50IG5vZGVzX3Blcl90aHJlYWQ7CgogIHN0ZDo6Y2luID4+IG51bWJlcl9vZl90aHJlYWRzID4+IG5vZGVzX3Blcl90aHJlYWQ7CgogIHN0ZDo6dmVjdG9yPGludDY0X3Q+IHYobnVtYmVyX29mX3RocmVhZHMsIG5vZGVzX3Blcl90aHJlYWQpOwogIHN0ZDo6Y291dCA8PCAiI3RocmVhZHM6ICIgPDwgbnVtYmVyX29mX3RocmVhZHMgPDwgIiwgI25vZGVzL3RocmVhZDogIiA8PCBub2Rlc19wZXJfdGhyZWFkIDw8ICIsIHBlcm11dGF0aW9uczogIiA8PCBmKHYpIDw8IHN0ZDo6ZW5kbDsKfQoK