G - How many ways??
构造矩阵,用于转移走一步的情况。
若\(i\)能走到\(j\),则\(g[j][i]=1\),否则为\(0\)
然后一开始只有\(A\)点累计有一种走法。
所以最后计算矩阵的\(k\)次方,输出\(g[B][A]\)即可。
#include<bits/stdc++.h>
using namespace std;
const int mod = 1000;
int n,m;
struct jz{
int g[25][25];
void init(){
memset(g,0,sizeof(g));
}
void one(){
memset(g,0,sizeof(g));
for(int i = 1; i <= n; ++ i) g[i][i] = 1;
}
};
jz operator * (jz a,jz b){
jz c; c.init();
for(int i = 1; i <= n; ++ i)
for(int j = 1; j <= n; ++ j)
for(int k = 1; k <= n; ++ k)
c.g[i][j] += a.g[i][k] * b.g[k][j] % mod, c.g[i][j] %= mod;
return c;
}
jz ksm(jz x,int y){
jz z; z.one();
while(y){
if(y & 1) z = z * x;
y >>= 1;
x = x * x;
}
return z;
}
jz mp,p;
int main(){
while(scanf("%d%d",&n,&m)){
if(n == 0 && m == 0) break;
mp.init();
for(int i = 1; i <= m; ++ i){
int x,y; scanf("%d%d",&x,&y);
++ x; ++ y;
mp.g[y][x] = 1;
}
int T; scanf("%d",&T);
while(T --){
int s,t,k; scanf("%d%d%d",&s,&t,&k);
++ s; ++ t;
p = ksm(mp,k);
printf("%d\n",p.g[t][s]);
}
}
return 0;
}