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

基准时间限制:1 秒 空间限制:131072 KB 分值: 160  难度:6级算法题
 收藏
 关注
四个机器人a b c d,在2 * 2的方格里,一开始四个机器人分别站在4个格子上,每一步机器人可以往临近的一个格子移动或留在原地(同一个格子可以有多个机器人停留),经过n步后有多少种不同的走法,使得每个毯子上都有1机器人停留。由于方法数量巨大,输出 Mod 10^9 + 7的结果。
Input
输入1个数N(0 <= N <= 10^9)
Output
输出走法的数量 Mod 10^9 + 7
Input示例
1
Output示例
9


解:这题有个很关键的条件就是每一个格子可以容纳多个机器人,那么直接求出每个机器人可以走的方法数的转移矩阵 用矩阵快速幂计算,最后统计合法数量即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
using namespace std;
typedef long long LL;
typedef vector<LL>a;
typedef vector<a>b;
const LL mod = 1000000007;
b jie(b m, b n)
{
    b z(m.size(),a(n[0].size()));
    for(int i=0; i<m.size(); i++)
    {
        for(int k=0; k<n.size(); k++)
        {
            for(int j=0; j<n[0].size(); j++)
            {
                z[i][j]=(z[i][j]+m[i][k]*n[k][j]%mod)%mod;
            }
        }
    }
    return z;
}
b Pow(b x,LL n,int m)
{
    b y(m,a(m));
    for(int i=0; i<m; i++)
        y[i][i]=1;
    while(n>0)
    {
        if(n&1)
        {
            y=jie(y,x);
        }
        x=jie(x,x);
        n>>=1;
    }
    return y;
}


int main()
{
    LL m, n;
    scanf("%lld",&n);
    if(n==0)
    {
        printf("1\n");
        return 0;
    }
    b x(4,a(4));
    x[0][0]=1,x[0][1]=1,x[0][2]=0,x[0][3]=1;
    x[1][0]=1,x[1][1]=1,x[1][2]=1,x[1][3]=0;
    x[2][0]=0,x[2][1]=1,x[2][2]=1,x[2][3]=1;
    x[3][0]=1,x[3][1]=0,x[3][2]=1,x[3][3]=1;
    x = Pow(x, n, 4);

    b y(4,a(4));
    y[0][0]=1,y[0][1]=0,y[0][2]=0,y[0][3]=0;
    y[1][0]=0,y[1][1]=1,y[1][2]=0,y[1][3]=0;
    y[2][0]=0,y[2][1]=0,y[2][2]=1,y[2][3]=0;
    y[3][0]=0,y[3][1]=0,y[3][2]=0,y[3][3]=1;
    y=jie(y,x);
    LL sum=0;
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<4;j++)
        {
            if(i==j) continue;
            for(int k=0;k<4;k++)
            {
                if(k==i||k==j) continue;
                for(int p=0;p<4;p++)
                {
                    if(p==i||p==j||p==k) continue;
                    sum=(sum+((y[0][i]*y[1][j]%mod)*(y[2][k]*y[3][p]%mod)%mod)%mod)%mod;
                }
            }
        }
    }
    printf("%lld\n",sum%mod);
    return 0;
}









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值