[SCOI2009] 迷路

当边权均为0或1时,我们是num[i][j][t]表示从i点到j点时间为t的方案数,将t拿出来,用矩阵快速幂进行优化,使得复杂度由O(Tn^3)变为O(logT n^3)。
那么现在对于边权不同的图怎么办呢?
我们将一个点拆为9个点来做。如果点i到点j有一条k的边,那么我们就连一条(i,k)到(j,1)的边。
而对于每个点拆成的9个点,在相邻两点之间进行连边。
最后,将矩阵累乘T次,用矩阵快速幂优化即可。
#include <bits/stdc++.h>
using namespace std;
const int MOD=2e3+9;
int n,t,m;
char str[21];
struct number{int num[201][201];}a,ans;

inline number mul(number a,number b)
{
	number c;	
	for (register int i=1; i<=n; ++i) 
	for (register int j=1; j<=n; ++j) c.num[i][j]=0;
	for (register int i=1; i<=n; ++i)
	for (register int j=1; j<=n; ++j)
	for (register int k=1; k<=n; ++k)
	c.num[i][j]=(c.num[i][j]+a.num[i][k]*b.num[k][j]%MOD)%MOD;
	return c;
}

inline void pow(int k)
{
	while (k)
	{
		if (k&1) ans=mul(ans,a);
		a=mul(a,a);	
		k>>=1;
	}
}

int main(){
	scanf("%d%d",&n,&t);
	m=n; n*=9;
	for (register int i=1; i<=m; ++i)
	for (register int j=1; j<=8; ++j)
	a.num[9*(i-1)+j][9*(i-1)+j+1]=1;
	
	for (register int i=1; i<=m; ++i)
	{
		scanf("%s",str+1);
		for (register int j=1; j<=m; ++j) 
		if (str[j]>'0') a.num[9*(i-1)+str[j]-'0'][9*(j-1)+1]=1;
	}
	for (register int i=1; i<=n; ++i) ans.num[i][i]=1;
	pow(t);
	printf("%d\n",ans.num[1][9*(m-1)+1]);
return 0;	
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值