#include #include #include #include #include // 解説通りに実装したもの。 // ただし前計算を怠っているため TLE になっている。 int main () { using mint = atcoder::modint; constexpr int kMaxN = 3000, kMinP = 100000000, kMaxP = 1000000000; int n, P; std::cin >> n >> P; assert(1 <= n && n <= kMaxN); assert(kMinP <= P && P <= kMaxP); mint::set_mod(P); constexpr int kOffset = 1; std::vector a(n, std::vector(3, std::vector(3, mint()))); for (int j = -1; j <= 1; ++j) { a[0][j + 1][j + 1] = mint::raw(1); } std::vector b(n, std::vector(3, std::vector(3, mint()))); for (int i = 0; i < n - 1; ++i) { for (int d = -1; d <= 1; ++d) { for (int e = -1; e <= 1; ++e) { if (e > 0) { a[i + 1][d + kOffset][e - 1 + kOffset] += a[i][d + kOffset][e + kOffset]; b[i + 1][d + kOffset][e - 1 + kOffset] += b[i][d + kOffset][e + kOffset]; } else if (e < 0) { a[i + 1][d + kOffset][e + kOffset] += a[i][d + kOffset][e + kOffset] / 2; b[i + 1][d + kOffset][e + kOffset] += b[i][d + kOffset][e + kOffset] / 2 + a[i][d + kOffset][e + kOffset] / 2; a[i + 1][d + kOffset][e + 1 + kOffset] += a[i][d + kOffset][e + kOffset] / 2; b[i + 1][d + kOffset][e + 1 + kOffset] += b[i][d + kOffset][e + kOffset] / 2; } else { a[i + 1][d + kOffset][e - 1 + kOffset] += a[i][d + kOffset][e + kOffset] / 2; b[i + 1][d + kOffset][e - 1 + kOffset] += b[i][d + kOffset][e + kOffset] / 2; a[i + 1][d + kOffset][e + kOffset] += a[i][d + kOffset][e + kOffset] / 4; b[i + 1][d + kOffset][e + kOffset] += b[i][d + kOffset][e + kOffset] / 4 + a[i][d + kOffset][e + kOffset] / 4; a[i + 1][d + kOffset][e + 1 + kOffset] += a[i][d + kOffset][e + kOffset] / 4; b[i + 1][d + kOffset][e + 1 + kOffset] += b[i][d + kOffset][e + kOffset] / 4; } } } } std::vector h(n, std::vector(3, mint())); for (int k = 0; k < n; ++k) { for (int d = -1; d <= 1; ++d) { h[k][d + kOffset] = std::accumulate(b[k][d + kOffset].begin(), b[k][d + kOffset].end(), mint()); assert(h[k][d + kOffset] == mint::raw(k) / 3 - (mint::raw(1) / 3 + d) * (mint::raw(4).pow(k) - 1) / 3 / mint::raw(4).pow(k)); } } std::vector p(n, std::vector(n, std::vector(3, mint()))); p[0][0][0 + kOffset] = 1; for (int i = 0; i < n - 1; ++i) { for (int x = 0; x <= i; ++x) { for (int d = -1; d <= 1; ++d) { if (d > 0) { p[i + 1][x + 1][d - 1 + kOffset] += p[i][x][d + kOffset]; } else if (d < 0) { p[i + 1][x][d + kOffset] += p[i][x][d + kOffset] / 2; p[i + 1][x][d + 1 + kOffset] += p[i][x][d + kOffset] / 2; } else { p[i + 1][x + 1][d - 1 + kOffset] += p[i][x][d + kOffset] / 2; p[i + 1][x][d + kOffset] += p[i][x][d + kOffset] / 4; p[i + 1][x][d + 1 + kOffset] += p[i][x][d + kOffset] / 4; } } } } for (int i = 0; i < n; ++i) { mint r = 1; for (int x = 0; x <= i; ++x) { for (int d = -1; d <= 1; ++d) { const int z = x + d, y = i - (x + z); if (d > 0) { r += p[i][x][d + kOffset] * (x + y + h[n - 1 - i][d - 1 + kOffset]); } else if (d < 0) { r += p[i][x][d + kOffset] * (mint::raw(y) / 2 + (n - 1 - h[n - 1 - i][d + 1 + kOffset]) / 2); } else { r += p[i][x][d + kOffset] * ((x + y + h[n - 1 - i][d - 1 + kOffset]) / 2 + mint::raw(y) / 4 + (n - 1 - h[n - 1 - i][d + 1 + kOffset]) / 4); } } } std::cout << r.val() << " \n"[i + 1 == n]; } return 0; }