LUOGU P4159 [SCOI2009]迷路(矩阵乘法)
解题思路
以前bpw讲过的一道题,顺便复习一下矩阵乘法。做法就是拆点,把每个点拆成\(9\)个点,然后挨个连边。之后若\(i\)与\(j\)之间的边长度为\(x\),就让\(i\)的第\(x\)个点和\(j\)的第\(1\)个点连边。然后就是一个矩阵快速幂,时间复杂度\(O((n*9)^3log(n*9))\)。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int MAXN = 15;
const int MOD = 2009;
typedef long long LL;
int n,T,cnt;
LL ans;
char s[MAXN];
struct Matrix{
int a[105][105];
void Clear(){
memset(a,0,sizeof(a));
}
friend Matrix operator*(const Matrix A,const Matrix B){
Matrix C;C.Clear();
for(register int i=1;i<=90;i++)
for(register int j=1;j<=90;j++)
for(register int k=1;k<=90;k++)
(C.a[i][j]+=((LL)A.a[i][k]*B.a[k][j]%MOD))%=MOD;
return C;
}
}mp,pre;
inline void fast_pow(Matrix x,int y){
for(;y;y>>=1){
if(y&1) pre=pre*x;
x=x*x;
}
}
int main(){
int x;
scanf("%d%d",&n,&T);cnt=n;
for(int i=1;i<=n;i++)
for(int j=1;j<=8;j++)
mp.a[(i-1)*9+j][(i-1)*9+j+1]=1;
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=n;j++){
x=s[j]-'0';if(x==0) continue;
mp.a[(i-1)*9+x][(j-1)*9+1]=1;
}
}
pre.Clear();n=n*9;
for(int i=1;i<=n;i++) pre.a[i][i]=1;
fast_pow(mp,T);
cout<<pre.a[1][n-8]<<endl;
return 0;
}