题目背景

在长沙城新建的环城公路上一共有8个公交站,分别为A、B、C、D、E、F、G、H。公共汽车只能够在相邻的两个公交站之间运行,因此你从某一个公交站到另外一个公交站往往要换几次车,例如从公交站A到公交站D,你就至少需要换3次车。

P2233 [HNOI2002]公交车路线_c

Tiger的方向感极其糟糕,我们知道从公交站A到公交E只需要换4次车就可以到达,可是tiger却总共换了n次车,注意tiger一旦到达公交站E,他不会愚蠢到再去换车。现在希望你计算一下tiger有多少种可能的乘车方案。

题目描述

输入输出格式

输入格式:

输入文件由bus.in读入,输入文件当中仅有一个正整数n(4<=n<=10000000),表示tiger从公交车站A到公交车站E共换了n次车。

输出格式:

输出到文件bus.out。输出文件仅有一个正整数,由于方案数很大,请输出方案数除以 1000后的余数。

输入输出样例

输入样例#1: 
6
输出样例#1: 
8

说明

8条路线分别是:

(A→B→C→D→C→D→E),(A→B→C→B→C→D→E),

(A→B→A→B→C→D→E),(A→H→A→B→C→D→E),

(A→H→G→F→G→F→E),(A→H→G→H→G→F→E),

(A→H→A→H→G→F→E),(A→B→A→H→G→F→E)。

 

Solution:

  本题简单矩阵加速dp。

  首先,一个很显然的dp是定义状态$f[i][j]$表示到了$i$点走了$j$步的方案数,则$f[i][j]=f[i-1][j-1]+f[i+1][j-1]$,注意的是$F\rightarrow E$和$D\rightarrow E$都是单向转移的。

  这样显然时空都会炸,空间还好解决,转移时直接滚掉第2维。

  时间上我们发现可以去掉$E$点改为统计$F,D$的方案数,而方案数是对称的,于是只需要统计一边的4个点的方案就好了。

  这样去直接dp是可以过的。

  但是还可以优化,根据优化后的4个点的dp转移构造矩阵

    初始矩阵:$[1,0,0,0]$,中间矩阵:$\begin{bmatrix}
 0& 1& 0& 0\\
 2& 0& 1& 0\\
 0& 1& 0& 1\\
 0& 0& 1& 0
\end{bmatrix}$

  最后答案就是$A[1,4]*2$啦。

代码:

/*Code by 520 -- 9.11*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
#define Clr(p) memset(&p,0,sizeof(p))
using namespace std;
const int mod = 1e3;
int n;
struct matrix{int a[4][4],r,c;};

il matrix Mul(matrix x,matrix y){
    matrix tp; Clr(tp);
    tp.r=x.r,tp.c=y.c;
    For(i,0,3) For(j,0,3) For(k,0,3)
        tp.a[i][j]=(tp.a[i][j]+x.a[i][k]*y.a[k][j]%mod)%mod;
    return tp;
}

il void solve(int k){
    matrix tp,ans; Clr(tp),Clr(ans);
    ans.r=1,ans.c=tp.r=tp.c=4;
    ans.a[0][0]=ans.a[1][1]=ans.a[2][2]=ans.a[3][3]=1;
    tp.a[1][0]=2,tp.a[0][1]=tp.a[1][2]=tp.a[2][1]=tp.a[2][3]=tp.a[3][2]=1;
    while(k){
        if(k&1) ans=Mul(ans,tp);
        k>>=1;
        tp=Mul(tp,tp);
    }
    printf("%d\n",2*ans.a[0][3]%mod);
}

int main(){
    cin>>n;
    solve(n-1);
    return 0;
}