XTU 1191 Hard Wuxing

Hard Wuxing

Accepted : 17   Submit : 179
Time Limit : 1000 MS   Memory Limit : 65536 KB

题目描述

“五行”是中国传统哲学思想,它认为认为大自然的现象由“木、火、土、金、水”这五种气的变化所总括, 不但影响到人的命运,同时也使宇宙万物循环不已。 五行具有相生相克的性质,规律如下:

  • 五行相克:金克木,木克土,土克水,水克火,火克金。
  • 五行相生:金生水,水生木,木生火,火生土,土生金。
  • 五行任一行与其他五行的关系为:同我、生我、我生、克我、我克。


给你一个1*n的格子,将五行填上去,每格填一个,要求相邻格以及首尾格不能是同我和相克的关系, 请问一共有多少种不同的方案?

 

输入

多组样例,每组一个整数n(0≤n≤1018),如果n为0,表示输入结束,这个样例不需要处理。

输出

每行输出一个样例的结果,因为数值可能非常大,请将结果对109+7取模。

样例输入

1
2
0


样例输出

5
10

先不看首尾格的限制
dp[i][j]表示i个格,首尾格关系为j的相邻格合法的方案数
j=0 首尾格相同
j=1 首尾格相生
j=2 首尾格相克
显然dp[n][1] 为所求。
dp[i][0] = dp[i-1][1]
dp[i][1] = dp[i-1][0]*2 + dp[i-1][2]
dp[i][w] = dp[i-1][1] + dp[i-1][2]

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
int dp[3333][3];
#define ll long long
const ll mod=1e9+7;
ll n;
struct matrix
{
    ll a[4][4];
    matrix() { memset(a,0,sizeof a); }
    void init()
    {
        a[0][0]=a[1][1]=a[2][2]=1;
    }
    matrix operator*(matrix b)
    {
        matrix t;
        for(int i=0;i<3;i++)
            for(int j=0;j<3;j++)
            for(int k=0;k<3;k++)
            t.a[i][j]+=a[i][k]*b.a[k][j],t.a[i][j]%=mod;
        return t;
    }
    void print()
    {
        for(int i=0;i<3;i++)
        {
            for(int j=0;j<3;j++)
                printf("%5d",a[i][j]);
            puts("");
        }
    }
};
matrix  powmod(matrix a, ll b)
{
    matrix e;
    e.a[0][0]=e.a[1][1]=e.a[2][2]=1;
    if(b==0) return e;
    if(b==1) return a;
    matrix t=powmod(a,b/2);
    t=t*t;
    if(b&1) t=t*a;
    return t;
}
int main()
{
    dp[1][0]=5; dp[1][1]=dp[1][2]=0;
    dp[2][0]=0; dp[2][1]=10; dp[2][2]=0;
    while(cin>>n&&n)
    {
        if(n==1) { cout<<5<<endl; continue; }
        if(n==2) { cout<<10<<endl; continue; }
        matrix a;
        a.a[0][0]=0;a.a[0][1]=2;a.a[0][2]=0;
        a.a[1][0]=1;a.a[1][1]=0;a.a[1][2]=1;
        a.a[2][0]=0;a.a[2][1]=1;a.a[2][2]=1;
        matrix c=powmod(a,n);       
        cout<<c.a[0][0]*5%mod<<endl;
    }
}


你可能感兴趣的:(XTU 1191 Hard Wuxing)