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;
}
posted @ 2018-10-19 22:20  Monster_Qi  阅读(178)  评论(0编辑  收藏  举报