bzoj1297: [SCOI2009]迷路

题目链接

bzoj1297: [SCOI2009]迷路

题解

若边权为1就是个矩阵快速幂裸题
因为权值<=10 ,对于每个点拆成9个点权值t就可以用t条权值为1的边表示

代码

/*
*/
#include<cstdio> 
#include<cstring> 
#include<algorithm> 
inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' || c > '9')c = getchar(); 
	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = getchar(); 
	return x * f; 
} 
const int mod = 2009; 
int n,t; 
struct Matrix { 
	int a[107][107]; 
	Matrix() {memset(a,0,sizeof a); } 
	Matrix operator * (const Matrix &b) const { 
		Matrix ret; 
		for(int k = 1;k <= n;++ k) 	
			for(int i = 1;i <= n;++ i) 
				for(int j = 1;j <= n;++ j) 
				ret.a[i][j] = (ret.a[i][j] + a[i][k] * b.a[k][j]) % mod; 
		return ret; 
	} 
} a; 
Matrix fstpow(int k) { 
	Matrix ret; 
	for(int i = 1;i <= n;++ i)ret.a[i][i] = 1; 
	for(;k;k >>= 1,a = a * a) 
		if(k & 1) ret = ret * a; 
	return ret; 
} 
int main() { 
	n = read(),t = read(); 
	for(int i = 1;i <= n;++ i) 
		for(int j = 9;j > 1;-- j) 
			a.a[(i - 1) * 9 + j][9 * (i - 1) + j - 1] = 1; 
	static char s[40]; 
	for(int i = 1;i <= n;++ i) { 
		scanf("%s",s + 1); 
		for(int j = 1;j <= n;++ j) { 
			int t = s[j] - '0'; 
			if(t) a.a[(i - 1) * 9 + 1][(j - 1) * 9 + t] = 1; 
		} 
	} 
	n *= 9; //for(int i = 1;i <= n;++ i) { for(int j = 1;j <= n;++ j) printf("%d ",a.a[i][j]); puts(""); } 
	Matrix ans = fstpow(t); 
	printf("%d\n",ans.a[1][n - 8]); 
	return 0; 
} 
posted @ 2018-08-10 21:14  zzzzx  阅读(116)  评论(0编辑  收藏  举报