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

题目大意

小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值