题目链接:http://acm.hit.edu.cn/hoj/problem/view?id=2930
本题是处理线性递推。
递推式:f[i] = 2*f[i-1] + f[i-3];
求线性递推问题可以转换为矩阵运算:
出任何一个线性递推式的第n项,其对应矩阵的构造方法为:在右上角的(n-1)*(n-1)的小矩阵中的主对角线上填1,矩阵第n行填对应的系数,其它地方都填0。例如,我们可以用下面的矩阵乘法来二分计算f(n) = 4f(n-1) - 3f(n-2) + 2f(n-4)的第k项:
a,b,c,d的顺序为项数的从低到高。
对于本题的递推式,f[i] = 2*f[i-1] + f[i-3];
我们可以构造连乘矩阵:
A= [0 1 0
0 0 1
1 0 2],
B = [f[0]
f[1]
f[2]]
则第n项f[n] = A^(n-2) * B.
另外用到矩阵的快速幂运算,用二分法就行了。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;
#define max 3
struct Matrix
{
int data[max][max];
};
Matrix A,B;
int n = 3;
int mod = 2010;
void init()
{
memset(A.data,0,sizeof(A.data));
memset(B.data,0,sizeof(B.data));
A.data[0][1] = 1;
A.data[1][2] = 1;
A.data[2][0] = 1;
A.data[2][2] = 2;
B.data[0][0] = 1;
B.data[1][0] = 1;
B.data[2][0] = 2;
}
//矩阵相乘
Matrix mul(Matrix u,Matrix v)
{
Matrix t;
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
t.data[i][j] = 0;
for(int k=0;k<n;k++)
{
t.data[i][j] += (u.data[i][k] * v.data[k][j])%mod;
t.data[i][j] %= mod;
}
}
}
return t;
}
//矩阵的幂
Matrix power(Matrix matrix,int k)
{
int k_temp = k;
Matrix result,a;
memset(result.data,0,sizeof(result.data));
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
a.data[i][j] = matrix.data[i][j];
if(i == j)
{
result.data[i][j] = 1;
}
//printf("%d ",a.data[i][j]);
}
//printf("\n");
}
while(k_temp)
{
if(k_temp&1)
{
result = mul(result,a);
}
a = mul(a,a);
k_temp = k_temp>>1;
}
return result;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int num;
init();
while(scanf(" %d",&num)!=EOF)
{
if(num == 1) printf("1\n");
else if(num == 2) printf("2\n");
else
{
Matrix temp = power(A,num - 2);
Matrix fin = mul(temp,B);
printf("%d\n",fin.data[2][0]);
}
}
return 0;
}