http://www.spoj.pl/problems/AMR10E
矩阵快速幂 处理出一个向后移k位的矩阵,外加一个求和系数
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
using namespace std;
long long x[9],a[9];
#define MOD 1000000007
#define Maxe 100
struct Matrix{
int m,n;
long long date[Maxe][Maxe];
Matrix(){
n=m=0;
memset(date,0,sizeof(date));
}
Matrix(int ne,int me):m(ne),n(me){
memset(date,0,sizeof(date));
}
Matrix operator * (const Matrix &a)
{
Matrix ret(m,a.n);
for (int i=0;i<m;i++)
for (int j=0;j<a.n;j++)
for (int k=0;k<a.m;k++)
ret.date[i][j]=(ret.date[i][j]+(date[i][k]*a.date[k][j])%MOD)%MOD;
return ret;
}
void set()
{
memset(date,0,sizeof(date));
for (int i=0;i<=max(m,n);i++)
date[i][i]=1;
return ;
}
};
Matrix pow_mod(Matrix a,int n)
{
Matrix temp(a.m,a.n);
temp.set();
Matrix T=a;
for (int i=n;i;i>>=1,T=T*T) if(i&1) temp=temp*T;
return temp;
}
int main ()
{
int r,k,n;
//freopen("date.in","r",stdin);
//freopen("date1.out","w",stdout);
int T;
scanf("%d",&T);
while (T--)
{
scanf("%d%d%d",&n,&r,&k);
for (int i=0;i<r;i++)
{
scanf("%lld",&x[i]);
}
for (int i=0;i<r;i++)
{
scanf("%lld",&a[i]);
}
Matrix T(r+1,r+1);
Matrix A(r+1,1);
for (int i=0;i<r;i++)
{
T.date[0][i]=a[i];
}
for (int i=1;i<r;i++)
{
T.date[i][i-1]=1;
}
for (int i=0;i<=r;i++)
{
T.date[r][i]=1;
}
for (int i=0;i<r;i++)
{
A.date[i][0]=x[r-1-i];
}
int t=k;
long long ans=0;
while (t<r) t+=k;
if(k<r)
{
for(int i=1;i<r;i++)
{
if((i%k)==0)
{
ans+=x[i-1];
}
}
}
for (int i=r;i<t;i++)
{
A=T*A;
}
T=pow_mod(T,k);
ans+=A.date[0][0];
A.date[r][0]=ans;
for (int i=0;i<r;i++)
{
T.date[r][i]=T.date[0][i];
}
T.date[r][r]=1;
A=pow_mod(T,(n-(t/k)))*A;
ans=A.date[r][0];
printf("%lld\n",ans%MOD);
}
return 0;
}