题目大意
小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走n步,但不能经过相同的点。小澳想知道他有多少种走法。
解题思路
f[i]表示可以走i步的答案,当i>4是f[i]=f[i-2]*3-f[i-2]*2+f[i-3]+f[i-4]。接着就是矩阵快速幂。
code
#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
#define LD double
#define max(a,b) ((a>b)?a:b)
#define min(a,b) ((a>b)?b:a)
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const inf=2147483647;
int const maxn=100000;
int n;
LL ans[10][10],mat[10][10],tmp[10][10],mod=1e9+7;
void multansmat(){
fo(i,1,4)fo(j,1,4)tmp[i][j]=0;
fo(i,1,4)
fo(j,1,4)
fo(k,1,4)
tmp[i][k]=(tmp[i][k]+ans[i][j]*mat[j][k])%mod;
fo(i,1,4)fo(j,1,4)ans[i][j]=tmp[i][j];
}
void multmatmat(){
fo(i,1,4)fo(j,1,4)tmp[i][j]=0;
fo(i,1,4)
fo(j,1,4)
fo(k,1,4)
tmp[i][k]=(tmp[i][k]+mat[i][j]*mat[j][k])%mod;
fo(i,1,4)fo(j,1,4)mat[i][j]=tmp[i][j];
}
int main(){
freopen("coordinate.in","r",stdin);
freopen("coordinate.out","w",stdout);
scanf("%d",&n);
ans[1][1]=1;ans[1][2]=3;ans[1][3]=7;ans[1][4]=17;
if(n<=3){
printf("%lld",ans[1][n+1]);
return 0;
}
n-=3;
mat[1][4]=mat[2][1]=mat[2][4]=mat[3][2]=mat[4][3]=1;
mat[3][4]=-2;mat[4][4]=3;
for(;n;){
if(n&1)multansmat();
multmatmat();
n=n>>1;
}
printf("%lld",ans[1][4]);
return 0;
}