LUOGU P4159 [SCOI2009]迷路(矩陣乘法)
阿新 • • 發佈:2018-10-20
span clear www. log oid 長度 truct lin scan
傳送門
解題思路
以前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; }
LUOGU P4159 [SCOI2009]迷路(矩陣乘法)