比赛的时候若是这题过了就进前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;
}