【洛谷P2233】[HNOI2002]公交车路线

题目背景

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

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)。

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n;
struct Mat{
    int m[6][6];
}c,dp;
inline Mat matmul(Mat a,Mat b,int len){
    Mat res;
    for(register int i=1;i<=4;++i)
    for(register int j=1;j<=len;++j){
        res.m[i][j]=0;
        for(register int k=1;k<=4;++k)
        res.m[i][j]=(res.m[i][j]+a.m[i][k]*b.m[k][j])%1000;
    }
    return res;
}
Mat matpow(Mat a,int p){
    Mat res=a;
    for(register int i=p-1;i;i>>=1,a=matmul(a,a,4))
        if(i&1) res=matmul(res,a,4);
    return res;
}
int main(){
    scanf("%d",&n);
    if(n&1||n<4){printf("%d\n",0); return 0;}
    c.m[1][1]=0;c.m[1][2]=2;c.m[1][3]=0;c.m[1][4]=0;
    c.m[2][1]=1;c.m[2][2]=0;c.m[2][3]=1;c.m[2][4]=0;
    c.m[3][1]=0;c.m[3][2]=1;c.m[3][3]=0;c.m[3][4]=1;
    c.m[4][1]=0;c.m[4][2]=0;c.m[4][3]=1;c.m[4][4]=0;
    dp.m[1][1]=1;dp.m[1][2]=dp.m[1][3]=dp.m[1][4]=0;
    c=matpow(c,n-1);
    c=matmul(c,dp,1);
    printf("%d\n",(c.m[4][1]<<1)%1000);
    return 0;
}

 

posted @ 2017-10-17 22:18  沐灵_hh  阅读(308)  评论(0编辑  收藏  举报