【jzoj5223】【GDOI2018模拟7.12】【B】【矩阵乘法】

本文介绍了一个关于3x3网格中机器人路径计数的问题,并提供了一种使用矩阵乘法来解决该问题的方法。具体步骤包括初始化矩阵、通过递归函数遍历所有可能的路径组合,并最终统计出每种状态下机器人分布的方案数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意

给定一个3*3的网格图,一开始每个格子上都站着一个机器人。每一步机器人可以走到相邻格子或留在原地,同一个格子上可以有多个机器人。问走n步后,有多少种走法,满足每个格子上都有机器人。答案对10^9+7取模。

解题思路

考虑到点数较小,暴力枚举每个点最后到哪里,用矩阵乘法算出从一个点到能一个点的方案数,乘起来即可。

code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define LF double
#define LL long long
#define ULL unsigned int
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
#define fr(i,j) for(int i=begin[j];i;i=next[i])
using namespace std;
int max(int x,int y){return (x>y)?x:y;}
int min(int x,int y){return (x<y)?x:y;}
int const mn=1e6+9,mo=1e9+7;
int a[20],vis[20];
LL n,anss,ans[20][20],mat[20][20],tmp[20][20];
void multansmat(){
    fo(i,1,9)fo(j,1,9)tmp[i][j]=0;
    fo(i,1,9)fo(j,1,9)fo(k,1,9)tmp[i][k]=(tmp[i][k]+ans[i][j]*mat[j][k])%mo;
    fo(i,1,9)fo(j,1,9)ans[i][j]=tmp[i][j];
}
void multmatmat(){
    fo(i,1,9)fo(j,1,9)tmp[i][j]=0;
    fo(i,1,9)fo(j,1,9)fo(k,1,9)tmp[i][k]=(tmp[i][k]+mat[i][j]*mat[j][k])%mo;
    fo(i,1,9)fo(j,1,9)mat[i][j]=tmp[i][j];
}
void dfs(int now){
    if(now>9){
        LL tmp=1;
        fo(i,1,9)tmp=tmp*ans[i][a[i]]%mo;
        anss=(anss+tmp)%mo;
        return;
    }
    fo(i,1,9)if(!vis[i]){
        a[now]=i;
        vis[i]=1;
        dfs(now+1);
        vis[i]=0;
    }
}
int main(){
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%lld",&n);
    fo(i,1,9)ans[i][i]=1;
    mat[1][1]=mat[1][2]=mat[1][4]=1;
    mat[2][1]=mat[2][2]=mat[2][3]=mat[2][5]=1;
    mat[3][2]=mat[3][3]=mat[3][6]=1;
    mat[4][1]=mat[4][4]=mat[4][5]=mat[4][7]=1;
    mat[5][2]=mat[5][4]=mat[5][5]=mat[5][6]=mat[5][8]=1;
    mat[6][3]=mat[6][5]=mat[6][6]=mat[6][9]=1;
    mat[7][4]=mat[7][7]=mat[7][8]=1;
    mat[8][5]=mat[8][7]=mat[8][8]=mat[8][9]=1;
    mat[9][6]=mat[9][8]=mat[9][9]=1;
    while(n){
        if(n&1)multansmat();
        multmatmat();
        n>>=1;
    }
    dfs(1);
    printf("%lld",anss);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值