题目 | Keep Connect
UNIQUE VISION Programming Contest 2022(AtCoder Beginner Contest 248)
F - Keep Connect
https://atcoder.jp/contests/abc248/tasks/abc248_f
Time Limit: 2 sec / Memory Limit: 1024 MB
Score :
Problem Statement
You are given an integer
Consider the graph
More specifically, the edges connect the vertices as follows, where the vertices are labeled as Vertex
- For each
, Edge connects Vertex and Vertex . - For each
, Edge connects Vertex and Vertex . - For each
, Edge connects Vertex and Vertex .
For each
Find the number of ways, modulo, to remove exactly of the edges of so that the resulting graph is still connected.
Constraints
is an integer. is a prime.
Input
Input is given from Standard Input in the following format:
Output
Print
Sample Input 1
3 998244353
Sample Output 1
7 15
In the case
There are
Thus, these numbers modulo
Sample Input 2
16 999999937
Sample Output 2
46 1016 14288 143044 1079816 6349672 29622112 110569766 330377828 784245480 453609503 38603306 44981526 314279703 408855776
Be sure to print the numbers modulo
我的笔记
首先将这个图的边
,即顶部的边,编号 ,如下图红边; ,即底部的边,编号 ,如下图蓝边; ,即中间的边,编号 ,如下图绿边。
然后把这个图的顶点
,即上面的一排点; ,即下面的一排点。
定义图
将图
- 状态
:图联通,如下图中上侧图。 - 状态
:图不连通,但有两个联通子图,并且两子图分别包含 、 ,如下图中下侧图。
然后运用动态规划思想,
首先初始化
然后寻找递推方法,先思考
如果新加的三条边
都保留,那么这个图会变成状态 ,如下图上面的情况(红色为新加的边)- 递推式:
+=
- 递推式:
如果新加的三条边
去掉 ,那么这个图仍然为状态 ,如下图下面的情况- 递推式:
+=
- 递推式:
再考虑
如果新加的三条边
都保留,那么这个图仍然为状态 ,如下图 号情况(红色为新加的边)- 递推式:
+=
- 递推式:
- 如果新加的三条边
去掉 ,那么这个图仍然为状态 ,如下图 号情况 - 如果新加的三条边
去掉 ,那么这个图仍然为状态 ,如下图 号情况 如果新加的三条边
去掉 ,那么这个图仍然为状态 ,如下图 号情况- 递推式均为:
+=
- 递推式均为:
- 如果新加的三条边
去掉 ,那么这个图会变成状态 ,如下图 号情况 如果新加的三条边
去掉 ,那么这个图会变成状态 ,如下图 号情况- 递推式均为:
+=
- 递推式均为:
时间复杂度:
代码
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 3100;
long long dp[MAXN][MAXN][2];
int N, P;
int main()
{
dp[0][0][0] = 1;
dp[0][1][1] = 1;
cin >> N >> P;
for (int i = 1; i < N; i++)
{
for (int j = 0; j < N; j++)
{
dp[i][j][0] += dp[i - 1][j][1];
dp[i][j][0] %= P;
dp[i][j + 1][1] += dp[i - 1][j][1];
dp[i][j + 1][1] %= P;
dp[i][j][0] += dp[i - 1][j][0];
dp[i][j][0] %= P;
dp[i][j + 1][0] += 3 * dp[i - 1][j][0];
dp[i][j + 1][0] %= P;
dp[i][j + 2][1] += 2 * dp[i - 1][j][0];
dp[i][j + 2][1] %= P;
}
}
for (int i = 1; i < N; i++)
cout << dp[N - 1][i][0] << ' ';
return 0;
}
本文采用 CC BY-SA 4.0 许可,本文 Markdown 源码:Haotian-BiJi