51nod 1122:机器人走方格 V4 (矩阵快速幂)

题目链接

昨天上随机信号分析讲马氏链的时候突然想到这题的解法,今天写一下

定义矩阵A,Ans=A^n,令A[i][j]表示,经过1次变换后,第i个位置上的机器人位于第j个位置的情况数,则Ans[i][j]表示最初在第i个位置上的机器人n次变换后位于第j个位置的情况数

最后求一下任意两个机器人不在相同位置的情况数之和(注意乘法原理和加法原理的应用)

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N=4;
const LL mod=1e9+7;

LL hh[N][N]= {{0,1,1,1},
    {1,0,1,1},
    {1,1,0,1},
    {1,1,1,0}
};

struct Mat
{
    LL mat[N][N];
    Mat()
    {
        memset(mat,0,sizeof(mat));
    }
    LL* operator [](int x)    //注意这种写法
    {
        return mat[x];
    }
} A;
Mat Mut(Mat a,Mat b)
{
    Mat c;
    for(int k=0; k<N; k++)
        for(int i=0; i<N; i++)
            for(int j=0; j<N; j++)
            {
                c[i][j]+=a[i][k]*b[k][j]%mod;
                c[i][j]=c[i][j]%mod;
            }
    return c;
}
Mat Qpow(Mat a,LL n)
{
    Mat c;
    for(int i=0; i<N; ++i)
        c[i][i]=1;
    for(; n; n>>=1)
    {
        if(n&1) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}

void init_A()
{
    for(int i=0; i<N; i++)
        for(int j=0; j<N; j++)
            A[i][j]=hh[i][j];
}

int main()
{
    LL n,Fn,Gn;
    init_A();
    while(cin>>n)
    {
        Mat Ans=Qpow(A,n);
        LL sum=0;
        for(int i1=0; i1<4; i1++)
            for(int i2=0; i2<4; i2++)
                for(int i3=0; i3<4; i3++)
                    for(int i4=0; i4<4; i4++)
                        if(i1!=i2&&i1!=i3&&i1!=i4&&i2!=i3&&i2!=i4&&i3!=i4)
                        {
                            sum+=Ans[0][i1]*Ans[1][i2]%mod*Ans[2][i3]%mod*Ans[3][i4]%mod;
                            sum%=mod;
                        }
        cout<<sum<<endl;
    }
}
原文地址:https://www.cnblogs.com/Just--Do--It/p/6597505.html