Loading

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]);
}
posted @ 2022-07-29 15:29  Into_qwq  阅读(26)  评论(1编辑  收藏  举报