// naive #include #include #include #include #include using mint = atcoder::modint; #include #include struct S { double p; mint mp; S() : S(0) {} template S(const T& x) : S(x, x) {} S(double p, mint mp) : p(p), mp(mp) {} friend S operator+(const S& a, const S& b) { return { a.p + b.p, a.mp + b.mp }; } friend S operator-(const S& a, const S& b) { return { a.p - b.p, a.mp - b.mp }; } friend S operator*(const S& a, const S& b) { return { a.p * b.p, a.mp * b.mp }; } friend S operator/(const S& a, const S& b) { return { a.p / b.p, a.mp / b.mp }; } }; int main() { int n, mod; std::cin >> n >> mod; mint::set_mod(mod); assert(n <= 20); std::map, int> ops; std::vector, S>> memo(n); for (int i = n - 1; i >= 0; --i) { for (int a = 0; a <= i; ++a) for (int b = 0; a + b <= i; ++b) { int c = i - a - b; auto dfs = [&](auto dfs, int j, int x, int y, int z, int v) -> S { std::tuple key{ j, a, b, c, x, y, z, v }; if (memo[i].count(key)) { return memo[i][key]; } if (j == n) { if (v == 0) { return memo[i][key] = y + z + a; } else if (v == 1) { return memo[i][key] = b; } else { return memo[i][key] = y + c; } } else { std::tuple op_key{ j, x + (v == 0), y + (v == 1), z + (v == 2) }; assert(ops.count(op_key)); int op = ops[op_key]; if (op == 0) { return memo[i][key] = dfs(dfs, j + 1, x, y, z + 1, v); } else if (op == 1) { return memo[i][key] = (dfs(dfs, j + 1, x + 1, y, z, v) + dfs(dfs, j + 1, x, y + 1, z, v)) / 2; } else { return memo[i][key] = (dfs(dfs, j + 1, x, y, z + 1, v) + (dfs(dfs, j + 1, x + 1, y, z, v) + dfs(dfs, j + 1, x, y + 1, z, v)) / 2) / 2; } } }; S v0 = dfs(dfs, i + 1, a, b, c, 2); S v1 = (dfs(dfs, i + 1, a, b, c, 0) + dfs(dfs, i + 1, a, b, c, 1)) / 2; if (std::abs(v0.p - v1.p) < 1e-6 and v0.mp == v1.mp) { assert(a == c); // ! ops[{i, a, b, c}] = 2; } else if (v0.p > v1.p) { assert(a < c); // ! ops[{i, a, b, c}] = 1; } else { assert(a > c); // ! ops[{i, a, b, c}] = 0; } } } std::vector R(n, 1); auto dfs = [&](auto dfs, int i, int x, int y, int z, mint p) -> void { if (i == n) return; std::tuple key{ i, x, y, z }; int op = ops[{i, x, y, z}]; if (op == 0) { R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 2}].mp; dfs(dfs, i + 1, x, y, z + 1, p); } else if (op == 1) { p /= 2; R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 0}].mp; R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 1}].mp; dfs(dfs, i + 1, x + 1, y, z, p); dfs(dfs, i + 1, x, y + 1, z, p); } else { p /= 2; R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 2}].mp; dfs(dfs, i + 1, x, y, z + 1, p); p /= 2; R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 0}].mp; R[i] += p * memo[i][{i + 1, x, y, z, x, y, z, 1}].mp; dfs(dfs, i + 1, x + 1, y, z, p); dfs(dfs, i + 1, x, y + 1, z, p); } }; dfs(dfs, 0, 0, 0, 0, 1); for (int i = 0; i < n; ++i) { if (i) std::cout << ' '; std::cout << R[i].val(); } std::cout << std::endl; }