题目:
给定一个3*3的网格图,一开始每个格子上都站着一个机器人。每一步机器人可以走到相邻格子或留在原地,同一个格子上可以有多个机器人。问走n步后,有多少种走法,满足每个格子上都有机器人。答案对10^9+7取模。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int mod=1e9+7;
struct node
{
long long m[9][9];
};
long long n;
int can[10][10];
long long e[9][9]={ {1,1,0,1,0,0,0,0,0},
{1,1,1,0,1,0,0,0,0},
{0,1,1,0,0,1,0,0,0},
{1,0,0,1,1,0,1,0,0},
{0,1,0,1,1,1,0,1,0},
{0,0,1,0,1,1,0,0,1},
{0,0,0,1,0,0,1,1,0},
{0,0,0,0,1,0,1,1,1},
{0,0,0,0,0,1,0,1,1} };
//转移矩阵存储的是1到9分别能到达的点
node mul(node a,node b)
{
node c;
memset(c.m,0,sizeof(c.m));
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
for(int k=0;k<9;k++)
(c.m[i][j]+=a.m[i][k]*b.m[k][j])%=mod;
return c;
}
node a,ans;
void qpow(long long b)
{
while(b)
{
if(b&1) ans=mul(ans,a);
b>>=1;
a=mul(a,a);
}
}
long long sum;
bool vis[10];
void dfs(int now,long long res)
{
if(now==9)
{
(sum+=res)%mod;
return;
}
for(int i=0;i<9;i++)
{
if(!vis[i])
{
vis[i]=1;
dfs(now+1,res*can[now][i]%mod);
vis[i]=0;
}
}
}
int main()
{
scanf("%lld",&n);
for(int k=0;k<9;k++)
{
for(int i=0;i<9;i++)
for(int j=0;j<9;j++)
a.m[i][j]=e[i][j];
memset(ans.m,0,sizeof(ans.m));
ans.m[0][k]=1;
qpow(n);
for(int i=0;i<9;i++) can[k][i]=ans.m[0][i];
}
dfs(0,1);
printf("%lld\n",sum%mod);
}