F - Keep Connect
F - Keep Connect --- UNIQUE VISION Programming Contest 2022(AtCoder Beginner Contest 248)
Editorial
solution
dp。定义dp[i][j][2],其中dp[i][j][1]表示前i列删除j条线联通图的方案数;dp[i][j][0]表示前i列删除j条线不连通图的方案数,该图中第i列中间线是不连接的,如果该线连接,那么该图则为连通图。
有以下状态转移方程:
\[\begin{cases}
dp[i][j][0] = (dp[i][j][0] + dp[i-1][j-1][0] + 2*dp[i-1][j-2][1])\%p; \\ dp[i][j][1] = (dp[i][j][1] + dp[i-1][j][1] + 3*dp[i-1][j-1][1]+ dp[i-1][j][0])\%p;
\end{cases}
\]
code
#include <bits/stdc++.h>
using namespace std;
const int NMAX = 3e3 + 10;
typedef long long ll;
ll dp[NMAX][NMAX][2];
int main() {
int n, p;
scanf("%d%d", &n, &p);
int ans = 0;
dp[1][0][1] = dp[1][1][0] = 1;
for(int i = 1;i <= n;i++) {
for(int j = 0;j < n;j++) {
dp[i][j][1] += dp[i-1][j][1] + (j > 0?3*dp[i-1][j-1][1]: 0) + dp[i-1][j][0];
dp[i][j][0] += (j > 0?dp[i-1][j-1][0]: 0) + (j > 1? 2*dp[i-1][j-2][1]: 0);
dp[i][j][1] %= p;
dp[i][j][0] %= p;
}
}
for(int i = 1;i < n;i++) printf("%lld%c", dp[n][i][1], i == n-1?'\n': ' ');
return 0;
}