1 1 1 2 2 0 0 3 7 23 47 16
一直都不太会矩阵的题,部长说一般都是先构造一列,然后乘个矩阵可以得到第二列,以此类推。。。找出这样的矩阵再用矩阵快速幂就行了。
这题可以发现每个数等于前一列行小于等于这一行的所有数相加,再加上233333那个东西。
设矩阵B,n+2行:
a1
a2
a3
..
233
3
矩阵A,n+2行:
1 0 0 ...1 0
1 1 0 0..1 0
1 1 1 0 .1 0
1 1 1 1. 1 0
0 0 0 0..10 0
0 0 0 0 ..0 1
最后答案是A^M * B,乘完之后第N行的数。
#include<iostream> #include<queue> #include<cstring> #include<cstdio> #include<cmath> #include<set> #include<map> #include<vector> #include<stack> #include<algorithm> #define INF 0x3f3f3f3f #define eps 1e-9 #define MAXN 15 #define MAXM 2000010 #define MAXNODE 105 #define MOD 10000007 #define SIGMA_SIZE 4 typedef long long LL; using namespace std; LL N,M,B[MAXN]; struct Mat{ LL mat[MAXN][MAXN]; Mat(){ memset(mat,0,sizeof(mat)); } }A; Mat operator * (Mat a,Mat b){ int i,j,k; Mat ret; for(int k=0;k<=N+1;k++) for(int i=0;i<=N+1;i++){ if(!a.mat[i][k]) continue; for(int j=0;j<=N+1;j++) ret.mat[i][j]=(ret.mat[i][j]+a.mat[i][k]*b.mat[k][j])%MOD; } return ret; } Mat operator ^ (Mat a,int n){ Mat ret,t=a; for(int i=0;i<=N+1;i++) for(int j=0;j<=N+1;j++) ret.mat[i][j]=(i==j); while(n){ if(n&1) ret=ret*t; t=t*t; n>>=1; } return ret; } void get_A(){ memset(A.mat,0,sizeof(A.mat)); for(int i=0;i<N;i++) for(int j=0;j<=i;j++) A.mat[i][j]=1; for(int i=0;i<N;i++) A.mat[i][N]=1; A.mat[N][N]=10; A.mat[N][N+1]=A.mat[N+1][N+1]=1; } int main(){ freopen("in.txt","r",stdin); while(scanf("%I64d%I64d",&N,&M)!=EOF){ for(int i=0;i<N;i++) scanf("%I64d",&B[i]); B[N]=233; B[N+1]=3; get_A(); A=A^M; LL ans=0; for(int i=0;i<=N+1;i++) ans=(ans+A.mat[N-1][i]*B[i])%MOD; printf("%I64d\n",ans); } return 0; }