HDU 2157 How many ways?? 矩阵快速幂

题意:春天到了, HDU校园里开满了花, 姹紫嫣红, 非常美丽. 葱头是个爱花的人, 看着校花校草竞相开放, 漫步校园, 心情也变得舒畅. 为了多看看这迷人的校园, 葱头决定, 每次上课都走不同的路线去教室, 但是由于时间问题, 每次只能经过k个地方, 比方说, 这次葱头决定经过2个地方, 那他可以先去问鼎广场看看喷泉, 再去教室, 也可以先到体育场跑几圈, 再到教室. 他非常想知道, 从A 点恰好经过k个点到达B点的方案数, 当然这个数有可能非常大, 所以你只要输出它模上1000的余数就可以了. 你能帮帮他么?? 你可决定了葱头一天能看多少校花哦(翻译的6不6偷笑


想法:用01矩阵存图,设i,j,k点,则矩阵自乘时会有此式子:mat[i][k]*mat[k][j],显然当i到k有路且k到j有路时才会使得它的解为1。那么mat的01矩阵从原来的图的存图矩阵变成了方案数矩阵了,如果i到k有mat[i][k]种方案,k到j有mat[k][j]种方案,那么i到j的方案显然是它俩相乘。


#include<iostream>
#include<cstring>
#include<cstdio>
#define mod 1000
using namespace std;
int n,m;
struct node
{
	int m[25][25];
}Mat,P,I;
node matmul(node a,node b)
{
	node c;
	for(int i=0;i<n;i++)
	{
		for(int j=0;j<n;j++)
		{
			c.m[i][j]=0;
			for(int k=0;k<n;k++)
			{
				c.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
			}
			c.m[i][j]%=mod;
		}
	}
	return c;
}
node quickpow(int num)
{
	node k=P,res=I;
	while(num>=1)
	{
		if(num&1)
		{
			res=matmul(res,k);
		}
		num=num>>1;
		k=matmul(k,k);
	}
	return res;
}
int main()
{
	while(~scanf("%d%d",&n,&m),n+m)
	{
		memset(P.m,0,sizeof(P.m));
		for(int i=1;i<=m;i++)
		{
			int a,b;
			scanf("%d%d",&a,&b);
			P.m[a][b]=1;
		}
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<n;j++)
			{
				I.m[i][j]=(i==j);
			}
		}
		int q;
		node res;
		scanf("%d",&q);
		for(int i=1;i<=q;i++)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			res=quickpow(c);
			printf("%d\n",res.m[a][b]);
		}
	}
	return 0;
}

你可能感兴趣的:(HDU 2157 How many ways?? 矩阵快速幂)