AT_dp_rWalk

Posted Syara

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了AT_dp_rWalk相关的知识,希望对你有一定的参考价值。

又是简单题。

我们知道弗洛伊德可以求解传递闭包

我们有矩阵 \\(M\\),我们给 \\(M_k,i,j\\) 定义为 \\(i\\to j\\) 长度为 \\(k\\) 的路径数,细想不难发现有转移:

  • \\(M_k,i,j=\\sum\\limits_p=1^n (M_k-1,i,p\\times M_1,p,j)\\)

直接暴力弗洛伊德得到了 \\(kn^3\\) 的上天复杂度。

我们发现这实际就是矩阵乘法,\\(M_k=M_k-1\\times M_1\\)

直接矩阵乘法即可——\\(M_k=M_1^k\\),结果为 \\(\\sum\\limits_i=1^n\\sum\\limits_j=1^n M_k,i,j\\)

得到了 \\(O(n^3\\log k)\\) 的做法。

通过记录

#include <stdio.h>
#include <string.h>
using namespace std;
int n;
long long k;
const int mod=1e9+7;
class Matrix
	public:
		long long s[105][105];
		void input()
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					scanf("%lld",&s[i][j]);
		
		void output()
			int ret=0;
			for(int i=1;i<=n;i++)
				for(int j=1;j<=n;j++)
					(ret+=s[i][j])%=mod;
			
			printf("%d",ret);
		
ans,mid,a;
Matrix operator *(const Matrix& a,const Matrix& b)
	memset(mid.s,0,sizeof mid.s);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			for(int k=1;k<=n;k++)
				mid.s[i][j]+=a.s[i][k]*b.s[k][j];
				mid.s[i][j]%=mod;
			
	return(mid);

int main()
	scanf("%d %lld",&n,&k);
	a.input();
	for(int i=1;i<=n;i++)ans.s[i][i]=1;
	while(k>0)
		if(k&1)ans=ans*a;
		a=a*a;
		k>>=1;
	
	ans.output();
	return(0);

以上是关于AT_dp_rWalk的主要内容,如果未能解决你的问题,请参考以下文章