1 条题解
-
0
自动搬运
来自洛谷,原作者为

Kevin_Zhen
不再回来搬运于
2025-08-24 22:14:24,当前版本为作者最后更新于2021-08-24 11:35:26,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
题目链接 。
可能更好的阅读体验。前置知识
邻接矩阵 的幂的意义:
记录图上任意两点 到 恰好经过 条边的路径数。对于最初的邻接矩阵 , 当且仅当存在一条边 。注意这里“当且仅当”的含义,如果 且 ,但 和 两点之间没有一条边直接相连,此时的 。那么换一个角度理解, 记录着图上任意两点 到 恰好经过 条边的路径数。
此时我们令矩阵 ,由矩阵乘法可知 ,实际上就等于枚举以 为中转点,从点 到点 恰好经过 条边的路径数。同理,如果要求经过 条边,计算 ,即 即可。那么普适地, 记录图上任意两点 到 恰好经过 条边的路径数。参考博客。
解题思路
对于停在原地的操作,不妨令每座城市连一条自环,理解为走过这条边后回到自己。
对于爆炸操作,不妨令每座城市连一条单向边指向 号结点,并使 号结点有且仅有一条出边指向自己,理解为机器人走到 号城市,然后在那不停兜圈。
问题转变为机器人每一秒必须走过一条边,求 秒后的行为方案数。
求出 ,然后记录 即可。注意: 号城市的自环是必需的。因为 记录的是恰好经过 条边。
AC CODE
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn = 110; const int Mod = 2017; struct Matrix { int a[maxn][maxn], n, m; int* operator [](int x) { return a[x]; } void clear() { n = 0, m = 0, memset(a, 0, sizeof(a)); } } a; Matrix operator *(Matrix &x, Matrix &y) { Matrix z; z.clear(); z.n = x.n, z.m = y.m; for (int i = 0; i <= x.n; ++i) { for (int j = 0; j <= x.m; ++j) { for (int k = 0; k <= y.m; ++k) z[i][k] = (z[i][k] + x[i][j] * y[j][k]) % Mod; } } return z; } Matrix qpow(Matrix &base, int p) { Matrix res = base; --p; while (p) { if (p & 1) res = res * base; base = base * base; p >>= 1; } return res; } int n, m, t, ans; int main() { scanf("%d%d", &n, &m); a.n = n, a.m = n; for (int i = 0; i <= n; ++i) a[i][i] = 1, a[i][0] = 1; for (int i = 1; i <= m; ++i) { int u, v; scanf("%d%d", &u, &v); a[u][v] = 1; a[v][u] = 1; } scanf("%d", &t); a = qpow(a, t); for (int i = 0; i <= n; ++i) ans = (ans + a[1][i]) % Mod; printf("%d", ans); return 0; }
- 1
信息
- ID
- 4630
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者