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

来源:互联网 发布:美业邦软件的弊端 编辑:程序博客网 时间:2024/05/22 03:08

题目大意

给定一个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;}
原创粉丝点击