ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂

Posted lhclqslove

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂相关的知识,希望对你有一定的参考价值。

题目链接:Poor God Water 

题意:有N个小时,有三种食物(用1 ,2 ,3代替好了),每个小时要吃一种食物,要求任意连续三个小时不能出现111,222,333,132,231,313,323

的方案数

题解:dp[i][j]表示最后两种食物分别为i,j的方案数,转移就是在增加一种食物,可以根据要求推出下面的递推矩阵.

技术分享图片

然后就可以用矩阵快速幂了。然后我还加了个离线的小优化(50ms)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
int n;
int an[1005];
struct  que
{
    ll x;
    int id;
    bool operator<(const que b)const
    {
        return x<b.x;
    }
}q[1005];
struct mat
{
    int n, m;
    ll a[15][15];
    mat() {}
    void init(int _n, int _m)
    {
        n = _n;
        m = _m;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++) a[i][j] = 0;
        }
    }
    void one()
    {
        init(2,2);a[0][0]=1;a[1][1]=1;
    }
    mat operator + (const mat &B)const
    {
        mat C;
        C.init(n,m);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
                C.a[i][j]=(a[i][j]+B.a[i][j])%mod;
        return C;
    }
    mat operator*(const mat &P)const
    {
        mat ret;
        ret.init(n,m);
        for(int i = 0; i < n; i++)
        {
            for(int k = 0; k < m; k++)
            {
                if(a[i][k])
                {
                    for(int j = 0; j < P.m; j++)
                    {
                        ret.a[i][j] = ((ll)a[i][k] * P.a[k][j] + ret.a[i][j]) % mod;
                    }
                }
            }
        }
        return ret;
    }
    mat operator^(const ll &P)const
    {
        ll num = P;
        mat ret, tmp = *this;
        ret.init(n,m);
        for(int i = 0; i < n; i++) ret.a[i][i] = 1;
        while(num)
        {
            if(num & 1) ret = ret * tmp;
            tmp = tmp * tmp;
            num >>= 1;
        }
        return ret;
    }
    void view()
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<m;j++)
            {
                printf("%lld ",a[i][j]);
            }printf("
");
        }
    }
}ap,ac,ad;
void init()
{
    ac.init(9,9);
    ac.a[3][0]=1;ac.a[6][0]=1;
    ac.a[0][1]=1;ac.a[3][1]=1;ac.a[6][1]=1;
    ac.a[0][2]=1;ac.a[3][2]=1;
    ac.a[1][3]=1;ac.a[4][3]=1;ac.a[7][3]=1;
    ac.a[1][4]=1;ac.a[7][4]=1;
    ac.a[1][5]=1;ac.a[4][5]=1;
    ac.a[2][6]=1;ac.a[8][6]=1;
    ac.a[5][7]=1;ac.a[8][7]=1;
    ac.a[2][8]=1;ac.a[5][8]=1;
    ad.init(9,9);
    for(int i=0;i<9;i++)
    {
        for(int j=0;j<9;j++)
        {
           ad.a[i][j]=ac.a[i][j];
        }
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    init();
    for(int i=1;i<=T;i++)
    {
        scanf("%lld",&q[i].x);
        q[i].id=i;
    }
    sort(q+1,q+T+1);
    ll p=3;
    for(int i=1;i<=T;i++)
    {
        if(q[i].x==1)
        {
            an[q[i].id]=3;
        }
        else if(q[i].x==2)
        {
            an[q[i].id]=9;
        }
        else
        {
            ad=ad*(ac^(q[i].x-p));
            p=q[i].x;
            ll ans=0;
            ap.init(1,9);
            for(int i=0;i<9;i++)
            {
                ap.a[0][i]=1;
            }
            ap=ap*ad;
            for(int i=0;i<9;i++)
            {
                ans+=ap.a[0][i];
                ans%=mod;
            }
            an[q[i].id]=ans;
        }
    }
    for(int i=1;i<=T;i++)
    {
        printf("%d
",an[i]);
    }
}

 

以上是关于ACM-ICPC 2018 焦作赛区网络预赛 Poor God Water 矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章

ACM-ICPC 2018 焦作赛区网络预赛 B题 Mathematical Curse

ACM-ICPC 2018 焦作赛区网络预赛 Solution

ACM-ICPC 2018 焦作赛区网络预赛 HL

ACM-ICPC 2018 焦作赛区网络预赛 G题 Give Candies

ACM-ICPC 2018 焦作赛区网络预赛 L 题 Poor God Water

Poor God Water(ACM-ICPC 2018 焦作赛区网络预赛 矩阵快速幂)