1 条题解
-
0
您指出的问题非常对,我之前的回答中确实还有一部分数字和公式没有用
$符号包裹。这是我的疏忽,非常抱歉。我将严格按照要求,修正所有格式问题。
题目理解
我们有一个机器人,初始在 号城市,每秒可以做三种行为之一:
1. 停留在当前城市(自环) 2. 走向相邻城市(有边相连) 3. 自爆(进入一个特殊状态,之后一直停留)
求经过 秒后,所有可能的行为序列(即状态转移路径)总数,对 取模。
核心思路
这个问题可以转化为 图上的带自环与自爆状态的步数计数问题。
1. 状态定义
设 表示经过 秒后位于节点 的方案数。
初始状态:,其余为 。
2. 状态转移
对于每个城市 :
- 可以停留在自身(自环)
- 可以走到相邻城市(邻接边)
- 可以自爆(进入一个特殊节点 )
自爆状态 是一个吸收态,只能停留在自身。
因此转移方程为:
其中 是转移矩阵, 表示可以从 到 。
3. 矩阵表示
我们构建一个大小为 的矩阵 ,下标 表示自爆状态, 表示城市。
矩阵构造规则:
- 邻接边:如果原图有边 ,则 ,。
- 自环:(每个城市和自爆状态都可以停留)。
- 自爆:(每个城市都可以自爆到状态 )。
这样,矩阵 的 次幂 中的元素 就表示从 到 经过 步的路径数。
4. 答案计算
初始时我们在城市 ,所以看 的第 行(代码中下标为 )的所有元素之和:
因为最终可以停留在任意城市或自爆状态,都算作不同的行为序列。
代码解析
#include <cstdio> #include <cstring> #include <cstdlib> #include <cctype> #include <cmath> #include <iostream> #include <algorithm> #include <vector> #include <set> #include <map> #include <queue> #include <stack> typedef long long ll; typedef unsigned long long ull; using namespace std; const int P = 2017; struct Matrix { int a[31][31]; // $0$~$30$ 共 $31$ 个节点,$0$ 号是自爆状态 inline Matrix operator * (const Matrix &rhs) { Matrix ret; memset(&ret, 0, sizeof ret); for (int i = 0; i <= 30; i++) for (int j = 0; j <= 30; j++) for (int k = 0; k <= 30; k++) (ret.a[i][j] += a[i][k] * rhs.a[k][j] % P) %= P; return ret; } } mp; Matrix ksm(Matrix &a, int b) { Matrix ret; memset(&ret, 0, sizeof ret); for (int i = 0; i <= 30; i++) ret.a[i][i] = 1; // 单位矩阵 while (b) { if (b & 1) ret = ret * a; a = a * a; b >>= 1; } return ret; } int u, v, n, m, t; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { scanf("%d%d", &u, &v); mp.a[u][v] = 1; mp.a[v][u] = 1; // 无向图邻接矩阵 } for (int i = 0; i <= n; i++) mp.a[i][i] = 1; // 自环:每个节点可以停留 for (int i = 1; i <= n; i++) mp.a[i][0] = 1; // 自爆:每个城市可以进入状态 $0$ int ans = 0; scanf("%d", &t); Matrix anss = ksm(mp, t); // 计算 $\text{mp}^t$ for (int i = 0; i <= n; i++) (ans += anss.a[1][i]) %= P; // 从 $1$ 出发,$t$ 秒后到任意状态 ($0$~$n$) 的方案数之和 printf("%d\n", ans); }
样例验证
样例输入:
3 2 1 2 2 3 2构造的矩阵( 共 个节点):
$$A = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 1 & 1 & 1 & 0 \\ 1 & 1 & 1 & 1 \\ 1 & 0 & 1 & 1 \end{bmatrix} $$计算 得到:
$$A^2 = \begin{bmatrix} 1 & 0 & 0 & 0 \\ 3 & 2 & 2 & 1 \\ 4 & 2 & 3 & 2 \\ 3 & 1 & 2 & 2 \end{bmatrix} $$第一行(对应节点 )的和 ,与样例输出一致。
复杂度分析
- 矩阵大小:,最大
- 矩阵乘法:
- 快速幂:
- 总复杂度:,在 , 时非常快。
总结
这道题的关键在于:
- 将三种行为统一建模为图上的边(邻接边、自环、自爆边)
- 引入自爆状态 作为吸收态
- 使用矩阵快速幂计算固定步数后的路径总数
- 答案 从起点到所有状态(包括自爆)的路径数之和
这个技巧广泛应用于计数类路径问题,特别是步数很大的情况。
- 1
信息
- ID
- 5022
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者