P4159 迷路题解
P4159 迷路
\(\text{A small trick about Matrix}\)
首先介绍一个有关邻接矩阵非常神奇的性质
假如我们现在有一个邻接矩阵 \(\text A\) ,并且边是没有边权的 (即只有 \(0/1\))
我们用 \(\text A^x\) 表示矩阵 \(\text A\) 的 \(x\) 次方
那么我们有:\(\text A^x_{i,j}\) 表示 \(i\) 经过 \(x\) 条边抵达 \(j\) 的方案数
至于为什么可以感性理解一下:
根据矩阵乘法的定义,我们显然有:
\[\text A^x_{i,j}=\sum\text A^{x-1}_{i,k}\times \text A_{j,k}
\]
也就可以理解成:从 \(i\) 走 \(x\) 条边到 \(j\) 相当于先走 \(x-1\) 条边到 \(k\) 再从 \(k\) 走一条边到 \(j\)
思路:
回到这道题
由于此题每条边边权 \(w\) 满足 \(1\le w\le 9\),显然我们不能直接利用上面的 \(trick\)
但是由于 \(w\) 很小,我们可以考虑把每 \(1\) 个点都拆成 \(9\) 个点来考虑
然后用矩阵快速幂搞就可以了
注:交的时候卡了下常,放的代码把 \(\text{IO}\) 去了
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
const int mod=2009;
struct matrix{
int n,A[181][181];
inline matrix(re int x){n=x,memset(A,0,sizeof(A));}
inline matrix operator *(const matrix B) const{
matrix C(n);
for(re int i=1;i<=n;++i)
for(re int j=1;j<=n;++j)
for(re int k=1;k<=n;++k)
C.A[i][j]=(C.A[i][j]+A[i][k]*B.A[k][j])%mod;
return C;
}
inline matrix operator ^(const int idx) const{
matrix res(n),B=*this;
for(re int i=1;i<=n;++i)
res.A[i][i]=1;
for(re int qwq=idx;qwq;qwq>>=1,B=B*B)
if(qwq&1) res=res*B;
return res;
}
};
int n,m;
inline int get_num(re int x,re int y){
return (x-1)*10+y;
}
signed main(){
read(n),read(m);
matrix f(180);
for(re int i=1;i<=n;++i){
for(re int j=1;j<10;++j)
f.A[get_num(i,j)][get_num(i,j+1)]=1;
for(re int j=1;j<=n;++j){
re int x;
scanf("%1d",&x);
if(x) f.A[get_num(i,x)][get_num(j,1)]=1;
}
}
f=f^m;
write(f.A[1][10*n-9]);
}