bzoj1297: [SCOI2009]迷路
题目链接
题解
若边权为1就是个矩阵快速幂裸题
因为权值<=10 ,对于每个点拆成9个点权值t就可以用t条权值为1的边表示
代码
/*
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
inline int read() {
int x = 0,f = 1;
char c = getchar();
while(c < '0' || c > '9')c = getchar();
while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar();
return x * f;
}
const int mod = 2009;
int n,t;
struct Matrix {
int a[107][107];
Matrix() {memset(a,0,sizeof a); }
Matrix operator * (const Matrix &b) const {
Matrix ret;
for(int k = 1;k <= n;++ k)
for(int i = 1;i <= n;++ i)
for(int j = 1;j <= n;++ j)
ret.a[i][j] = (ret.a[i][j] + a[i][k] * b.a[k][j]) % mod;
return ret;
}
} a;
Matrix fstpow(int k) {
Matrix ret;
for(int i = 1;i <= n;++ i)ret.a[i][i] = 1;
for(;k;k >>= 1,a = a * a)
if(k & 1) ret = ret * a;
return ret;
}
int main() {
n = read(),t = read();
for(int i = 1;i <= n;++ i)
for(int j = 9;j > 1;-- j)
a.a[(i - 1) * 9 + j][9 * (i - 1) + j - 1] = 1;
static char s[40];
for(int i = 1;i <= n;++ i) {
scanf("%s",s + 1);
for(int j = 1;j <= n;++ j) {
int t = s[j] - '0';
if(t) a.a[(i - 1) * 9 + 1][(j - 1) * 9 + t] = 1;
}
}
n *= 9; //for(int i = 1;i <= n;++ i) { for(int j = 1;j <= n;++ j) printf("%d ",a.a[i][j]); puts(""); }
Matrix ans = fstpow(t);
printf("%d\n",ans.a[1][n - 8]);
return 0;
}