首页 > 代码库 > 2014 ACM/ICPC Asia Regional Xi'an Online 233 Matrix,hdu 5015

2014 ACM/ICPC Asia Regional Xi'an Online 233 Matrix,hdu 5015

比赛的时候若是这题过了就进前50

刚开始的时候大家的思路都以为是找规律的题目,于是再推公式,此外还发现类似于杨辉三角。于是又去套杨辉三角的通项去求。

于是TLE了无数次。(每次取范围的最大值也要3s多)。

对于明显的矩阵样子,其实可以转化为矩阵的运算,每一行的转移。就是对一个转移矩阵的幂运算。然后再用快速矩阵幂即可。

A:

10 0 0 1

10 1 0 1

10 1 1 1

0  0  0 1

B:

23

0

0

3

C=A^M  *B,ans=C[N]

教训:对于时间限制,即便是最大数据也要秒出才行,不要以为刚刚好够就可以。矩阵的妙用无处不在···~~~~

#pragma comment(linker, "/STACK:1024000000,1024000000")  
#include<stdio.h>
#include<string>
typedef __int64 LL;
#define INF 10000007
#define MAX 100000
int N,M;
LL A[12][12];//init
LL B[12];//init
LL C[12][12];//ans
LL T[12][12];//temp
LL D[12][12];
void matrix(LL (*a)[12],LL (*b)[12],LL (*c)[12])
{
	int i,j,k;
	LL sum;
	for(i=0;i<=N+1;i++)
	{
		
		for(j=0;j<=N+1;j++)
		{sum=0;
			for(k=0;k<=N+1;k++)
				sum=sum+(a[i][k]*b[k][j])%INF,sum%=INF;
			c[i][j]=sum;
		}
			
	}
}//刚开始连这个都出错。

void Cal()
{
	//memcpy(C,A,sizeof(A));
	int i,j,k;
	k=M;
	while(k)
	{
		i=k&1;
		while(i==0)
		{
			matrix(A,A,T);
			memcpy(A,T,sizeof(T));
			k>>=1;i=k&1;
		}
		matrix(C,A,T);
		memcpy(C,T,sizeof(T));
		matrix(A,A,T);//快速算完后还要再乘一次到下一位,C刚开始设置为单位矩阵
		memcpy(A,T,sizeof(T));
		k>>=1;
	}
	/*for(i=0;i<=N+1;i++)
		{	for(j=0;j<=N+1;j++)
				printf("%d ",C[i][j]);
			printf("\n");
		}*/
	for(i=0;i<=N+1;i++)
	{
		LL sum=0;
		for(j=0;j<=N+1;j++)
			sum=sum+(C[i][j]*B[j])%INF,sum%=INF;
		A[0][i]=sum;			
	}
	printf("%d\n",A[0][N]);
}


int main() {

	while(scanf("%d%d",&N,&M)!=EOF)
	{
		int i,j;
		for(i=1;i<=N;i++)
			scanf("%d",B+i);
		B[i]=3;B[0]=23;
		memset(A,0,sizeof(A));memset(C,0,sizeof(C));
		for(i=0;i<=N;i++) A[i][0]=10,A[i][N+1]=1,C[i][i]=1;//单位矩阵
		C[i][i]=1;A[N+1][N+1]=1;		
		for(i=1;i<N+1;i++)
			for(j=1;j<=i;j++)
				A[i][j]=1;
	/*	for(i=0;i<=N+1;i++)
		{	for(j=0;j<=N+1;j++)
				printf("%d ",A[i][j]);
			printf("\n");
		}*/
		
		
		Cal();
			
	}
	
	return 0;
}


2014 ACM/ICPC Asia Regional Xi'an Online 233 Matrix,hdu 5015