您的位置:首页 > 其它

【jzoj4854】【小澳的坐标系】【动态规划】【矩阵快速幂】

2016-11-03 15:31 267 查看

题目大意

小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走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("sunset.in","r",stdin);
//freopen("sunset.out","w",stdout);
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: