MZ test17# NOIP模拟题 # T4 第4题 路线统计(route.cpp/pas)[key:矩阵]

第4题 路线统计(route.cpp/pas)

 

【问题描述】

给出一个n个点有向图,求从s点到f点恰好经过时间t的路径总数。不能在某个点停留,可以重复的走各点。

 

【输入数据】

第一行包含一个整数n, 所有点是从0到n-1编号.

接下来n行,每行包含n个字符. 第i行第j个字符表示i到j需要的时间,字符只可能是’1’到’5’, 或者是’.’表示i不能到达j, 保证主对角线都是’.’。

接下来一行3个整数s, f, t。

 

【输出数据】

输出总方案数mod 502630的值。

 

【样例输入】route.in

3

.12

2.1

12.

0 2 5

 

【样例输出】route.out

8

 

【数据范围及提示】

对于20%的数据, 输入的字符不是’1’就是’.’;

对于100%的数据, 1 <= n <= 10; 1 <= s,f <= n; 1 <= t <= 10^9

 

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;

const int MOD=502630;
struct matrix
{
  int f[55][55];  
  void clear()
  {
  	memset(f,0,sizeof(f));
  }  
}st,ans,E;

int n;
char s[15];
void readdata()
{
  st.clear();	
  scanf("%d",&n);  
  for(int i=1;i<=n;i++)
  {
  	scanf("%s",s);
  	for(int j=1;j<=n;j++)
  	{
  	  if(s[j-1]!='.')
  	  {
  	  	int ret=s[j-1]-'0';
  	  	for(int k=1;k<ret;k++)
  	  	{
  	  		st.f[(k-1)*n+i][k*n+i]=1;
  	  	}
  	  	st.f[(ret-1)*n+i][j]=1;
  	  }
  	}
  }
  
  n*=5;  
  E.clear();  
  for(int i=1;i<=n;i++)E.f[i][i]=1;  
}

matrix o_o(matrix a,matrix b)
{ 
  matrix c;
  c.clear();
  for(int i=1;i<=n;i++)
  for(int j=1;j<=n;j++)
  for(int k=1;k<=n;k++)
  {
  	c.f[i][j]=(c.f[i][j]+((long long)a.f[i][k]*b.f[k][j])%MOD)%MOD;
  }
  return c;
}

matrix mult(matrix a,int t)
{
  matrix c=E;
  while(t)
  {
  	if(t%2)c=o_o(c,a);  	
  	t>>=1;  	
  	a=o_o(a,a);
  }
  return c;
}

void work()
{
  int start,finish,t;	
  scanf("%d%d%d",&start,&finish,&t);
  start++;finish++;  
  matrix ans=mult(st,t);  
  printf("%d\n",ans.f[start][finish]);  
}

int main()
{
	freopen("route.in","r",stdin);
	freopen("route.out","w",stdout);
	readdata();	
	work();	
	return 0;
}

附glk's code.

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mod = 502630;
#define LL long long
struct Mat{
	int A[300][300];
	int h,l;
	Mat() {memset(A,0,sizeof(A));h = l = 0;}
	Mat operator * (const Mat& B)const{
		Mat C;
		C.h = h;C.l = B.l;
		for(int i = 1;i <= h;++i)
		for(int j = 1;j <= B.l;++j){
			int tmp = 0;
			for(int k = 1;k <= l;++k)
			tmp = (tmp + ((LL)A[i][k] * B.A[k][j])%mod)%mod;
			C.A[i][j] = tmp;
		}
		return C;
	}
};

char Can[15][15];

Mat Pow(Mat B,int n){
	Mat ans = B;
	for(int i = 1;i <= B.h;++i)
	for(int j = 1;j <= B.l;++j)
	ans.A[i][j] = (i==j);
	while(n){
		if(n&1) ans = ans * B;
		B = B * B;
		n>>=1;
	}
	return ans;
}

int main(){
	freopen("route.in","r",stdin);
	freopen("route.out","w",stdout);
	//A*A为t=2,A^k means  t = k + 1
	//ans = A^(t-1)[s,f]
	int n,tot,s,f,t;
	scanf("%d",&n);
	for(int i = 1;i <= n;++i)scanf("%s",Can[i]+1);
	tot = n;
	scanf("%d%d%d",&s,&f,&t);
	++s,++f;
	Mat B;
#define CC B.A
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= n;++j){
			if(Can[i][j]=='.') continue;
			int tmp = Can[i][j]-'0';
			for(int k = 1;k < tmp;++k)
			CC[(k-1)*n+i][k*n+i] = 1;
			CC[(tmp-1)*n+i][j] = 1;
		}
	}
	B.h = B.l = n * 5;
	Mat ans = Pow(B,t);
	printf("%d",ans.A[s][f]);
	return 0;
}


你可能感兴趣的:(矩阵)