我做的时候构造了2个矩阵,一个是形如
1 1 1 1
0 1 1 1
0 0 1 1
0 0 0 1
另一个形如
10 0 0 0 0
1 1 0 0 0
0 0 1 1 1
0 0 0 1 1
0 0 0 0 1
然后就可以分别对给出第一列的数字乘上第一个矩阵的^m,第一行的(233,1,0,0,0.。。)乘以第二个矩阵的^m,用矩阵快速幂复杂度就只有log(m),然后加上这2个矩阵的右下角就可以了,总复杂度n*log(m)。。尼玛写的时候那个取模写成10^9+7简直哭了。。找了半小时比赛结束才发觉。。。还有看了别人的才发觉原来可以合起来。。懒得改了。
AC代码:
#include<cstdio>
#include<ctype.h>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<stack>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<ctime>
#include<string.h>
#include<string>
using namespace std;
#define ll __int64
#define eps 1e-6
#define MOD 10000007
struct matrix
{
ll a[12][12];
};
int n;
inline void init(matrix &res)
{
memset(res.a,0,sizeof(res.a));
for(int i=0;i<n;i++)
res.a[i][i]=1;
}
matrix multiply(matrix x,matrix y,int flag)
{
matrix temp;
memset(temp.a,0,sizeof(temp.a));
for(int k=0;k<n;k++)
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
temp.a[i][j]+=(x.a[i][k]*y.a[k][j]);
temp.a[i][j] %= MOD;
}
if(flag) break;
}
return temp;
}
void calc(ll num,matrix ori,matrix &res)
{
while(num)
{
if(num&1)
res=multiply(ori,res,0);
num>>=1;
ori=multiply(ori,ori,0);
}
}
int main()
{
#ifdef GLQ
freopen("input.txt","r",stdin);
// freopen("o2.txt","w",stdout);
#endif // GLQ
int i,j;
ll m;
while(~scanf("%d%I64d",&n,&m))
{
matrix ori;
memset(ori.a,0,sizeof(ori.a));
for(i = 0; i < n; i++)
scanf("%I64d",&ori.a[0][i]);
matrix x1;
memset(x1.a,0,sizeof(x1.a));
for(j = 0; j < n; j++)
for(i = 0; i <= j; i++)
x1.a[i][j] = 1;
matrix a1;
init(a1);
calc(m,x1,a1);
ori = multiply(ori,a1,1);
ll ans = ori.a[0][n-1];
memset(ori.a,0,sizeof(ori.a));
ori.a[0][0] = 233;
ori.a[0][1] = 1;
memset(x1.a,0,sizeof(x1.a));
for(i = 0; i < n+2; i++)
{
x1.a[0][i] = 1;
}
x1.a[1][0] = 3;
x1.a[0][0] = 10;
for(j = 2; j < n+2; j++)
for(i = 2; i <= j; i++)
x1.a[i][j] = 1;
x1.a[0][1] = 0;
x1.a[1][1] = 1;
n += 2;
init(a1);
calc(m,x1,a1);
ori = multiply(ori,a1,1);
ans += ori.a[0][n-1];
ans %= MOD;
printf("%I64d\n",ans);
}
return 0;
}