【题目来源】:https://vjudge.net/problem/FZU-1683
【题意】
题意就像题面描述。
【思路】
这道题和我上一道题Arc of Dream非常相似,并且我在那篇博客里也写的非常详细,所以这里就直接写怎么推导:
设前n项和:S
那么:S[i]=S[i-1]+F[i]
接着:F[i]=3*F[i-1]+2*F[i-2]+7*F[i-3]
代入:S[i]=S[i-1]+3*F[i-1]+2*F[i-2]+7*F[i-3]。
写出系数矩阵:
1 3 2 7
0 3 2 7
0 1 0 0
0 0 1 0
然后,必须强调的一点就是,这道题的数据不符合题意范围:
明明是n>=3,却依旧存在n<3的情况。。。
【代码】
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
const LL mod=2009;
struct mat
{
LL a[5][5];
};
mat operator*(mat &s,mat &t)
{
mat r;
memset(r.a,0,sizeof(r.a));
for(int i=1; i<=4; i++)
{
for(int j=1; j<=4; j++)
{
for(int k=1; k<=4; k++)
{
r.a[i][j]+=s.a[i][k]*t.a[k][j];
if(r.a[i][j]>=mod)
r.a[i][j]%=mod;
}
}
}
return r;
}
LL pow_mat(mat base,LL k)
{
mat ans;
for(int i=1; i<=4; i++)
for(int j=1; j<=4; j++)
ans.a[i][j]=(i==j);
while(k)
{
if(k&1)
{
ans=ans*base;
}
base=base*base;
k>>=1;
}
return (ans.a[1][1]*9+ans.a[1][2]*5+ans.a[1][3]*3+ans.a[1][4])%mod;
}
int main()
{
int T,cases=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
if(n==0)
printf("Case %d: 1\n",cases++);
else if(n==1)
printf("Case %d: 4\n",cases++);
else if(n==2)
printf("Case %d: 9\n",cases++);
else
{
mat base;
memset(base.a,0,sizeof(base.a));
base.a[1][1]=1;
base.a[1][2]=3;
base.a[1][3]=2;
base.a[1][4]=7;
base.a[2][2]=3;
base.a[2][3]=2;
base.a[2][4]=7;
base.a[3][2]=1;
base.a[4][3]=1;
LL ans=pow_mat(base,n-2);
printf("Case %d: %lld\n",cases++,ans);
}
}
}