题意:求A经过K个点到B方案数
1个0 1 的矩阵 A
a[i][j] = 1 表示i 到 j可达 或者说 i 到 j 有1条路 或者说i到j经过一个点的方案数 路可以重复走
而A2 = A* A
a[i][j] 的含义是
从i到j经过2个点的方案数
A的k次方 A[i,j]代表 i到j走k步的方案有a[i][j]
T组询问 x y z 快速幂求出A矩阵的y次 然后输出A[x][y]
#include <cstdio> #include <cstring> const int mod = 1000; const int maxn = 22; struct Mat { int a[maxn][maxn]; }; Mat A, B, C, D; int n, m; Mat get(Mat x, Mat y) { Mat z; memset(z.a, 0, sizeof(z.a)); for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) for(int k = 1; k <= n; k++) { z.a[i][j] += x.a[i][k]*y.a[k][j]; z.a[i][j] %= mod; } return z; } void Mat_pow(int n) { //puts("s"); if(n <= 0) return; while(n) { if(n&1) B = get(A, B); A = get(A, A); n >>= 1; } } int main() { while(scanf("%d %d", &n, &m) && (n+m)) { memset(D.a, 0, sizeof(D.a)); memset(C.a, 0, sizeof(C.a)); while(m--) { int u, v; scanf("%d %d", &u, &v); u++; v++; D.a[u][v] = 1; } for(int i = 1; i<= n; i++) C.a[i][i] = 1; int T; scanf("%d", &T); while(T--) { int u, v, w; scanf("%d %d %d", &u, &v, &w); u++; v++; B = C; A = D; Mat_pow(w); printf("%d\n", B.a[u][v]); } } return 0; }