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

hs_black
Go for broke搬运于
2025-08-24 21:39:17,当前版本为作者最后更新于2019-10-28 23:53:14,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
机房大佬讲解后, 写一写题解
这是很经典的邻接矩阵乘法了
对于邻接矩阵G[i][j] 表示i到j有没有边
如果是 , 发现就是原矩阵, G[i][j]可以理解为从i走一步到j的方案数
下面考虑
矩阵乘法代码:
Matrix operator * (const Martix &p) const{ Martix tmp; for (rint i = 0;i < n; i++) for (rint j = 0;j < n; j++) for (rint k = 0;k < n; k++) tmp.Mar[i][j] = (tmp.Mar[i][j] + Mar[i][k] * p.Mar[k][j]) % P; return tmp; }发现 像不像Floyd
即枚举一个中间点k, 从i到j走两步的的方案数等于从i到走一步k的方案数, 再乘上从k走一步到j的方案数之和
以此类推
为再G这个邻接矩阵上从i走t步到j的方案数
原矩阵为单位矩阵, 每乘一个新的邻接矩阵相当于又在新的邻接矩阵上走一步
回到本题
2, 3, 4的最小公倍数为12
所以开十二个邻接矩阵即可, 每个矩阵表示当前走一步的合法情况
a[0]表示走12步的矩阵, 即12个邻接矩阵之积
k/12个a[0]相乘使用快速幂, 在按顺序从a[1]乘到a[k%12]
答案为
细节见代码及注释:
#include<iostream> #include<cstdio> #include<cstring> #define ll long long using namespace std; template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (;!isdigit(c);c=getchar()) if (c=='-') f=-1; for (;isdigit(c);c=getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; }//快读 const int N = 52; int n, m; ll t, k; const int P = 10000; #define rint register int struct matrix{ int Mar[N][N]; matrix () { memset(Mar, 0, sizeof(Mar)); } matrix operator * (const matrix &p) const{ matrix tmp; for (rint i = 0;i < n; i++) for (rint j = 0;j < n; j++) for (rint k = 0;k < n; k++) tmp.Mar[i][j] = (tmp.Mar[i][j] + Mar[i][k] * p.Mar[k][j]) % P; return tmp; }//矩阵乘法 void print(void) { for (int i = 0;i < n; i++) { for (int j = 0;j < n; j++) printf ("%d ", Mar[i][j]); cout << endl; } cout << endl; }//调试输出 }a[15], b, c; matrix pow() { matrix ans = b, tmp = a[0]; int tttmp = k / 12; while (tttmp) { if (tttmp & 1) ans = ans * tmp; tmp = tmp * tmp; tttmp >>= 1; } return ans; }//矩阵快速幂 int nfish, ttmp[50], st, ed; int main() { // freopen("hs.out","w",stdout); read(n), read(m), read(st), read(ed), read(k); while (m--) { int x, y; read(x), read(y); c.Mar[x][y] = c.Mar[y][x] = 1; //原矩阵 } // c.print(); for (rint i = 1;i <= 12; i++) a[i] = c; //初始化 for (rint i = 0;i < n; i++) b.Mar[i][i] = 1; //单位矩阵 read(nfish); while (nfish--) { read(t); for (int i = 0;i < t; i++) read(ttmp[i]); ttmp[t] = ttmp[0]; //由于开始时时间为0, 所以读入要从零开始 for (int i = 1;i <= 12; i++) for (int j = 0;j < n; j++) a[i].Mar[j][ttmp[(i-1)%t+1]] = 0; //注意只清空从其他地方到鳄鱼新来的地点的边 } // for (int i = 1;i <= 12; i++) a[i].print(); a[0] = b; for (int i = 1;i <= 12; i++) a[0] = a[0] * a[i]; // a[0].print(); matrix ans = pow(); for (int i = 1;i <= k % 12; i++) ans = ans * a[i]; cout << ans.Mar[st][ed] << endl; return 0; }
- 1
信息
- ID
- 1617
- 时间
- 1000ms
- 内存
- 125MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者