链接
题目描述
有一个3*3的网格,现在每个网格上有一个机器人,每个机器人在一个单位时间后会向四方任意一个方向进行移动,问t秒后不同的方案数
思路
DP转移,矩阵快速幂加速一个点到别的点的情况求解
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
const int dx[4] = {
-1, 0, 0, 1}, dy[4] = {
0, -1, 1, 0};
const ll mo = 1e9 + 7;
struct matrix
{
int n, m;
ll a[15][15];
} A, B, ans;
int p[15][15], w[15];
ll n, sum, Ans, t, f[15][15];
bool use[15];
matrix operator * (matrix a, matrix b)
{
matrix c;
c.n = a.n, c.m = b.m;
for (int i = 1; i <= c.n; i++)
for (int j = 1; j <= c.m; j++) c.a[i][j] = 0;
for (int i = 1; i <= c.n; i++)
for (int j = 1; j <= c.m; j++)
for (int k = 1; k <= a.m; k++)
c.a[i][j] = (c.a[i][j] + a.a[i][k] * b.a[k][j] % mo) % mo;
return c;
}
void ksm(ll t)
{
if(t == 1) {
B = A;
return;
}
ksm(t >> 1);
B = B * B;
if(t & 1) B = B * A;
}
ll work(int x, int y)
{
ans.n = 1; ans.m = 9;
for(int i = 1; i <= 9; ++i) ans.a[1][i] = 0;
ans.a[1][x] = 1;
ans = ans * B;
return ans.a[1][y];
}
void dfs(int x)
{
if(x > 9) {
sum = 1;
for(int i = 1; i <= 9; ++i)
sum = sum * f[i][w[i]] % mo;
Ans = (Ans + sum) % mo;
return;
}
for(int i = 1; i <= 9; ++i)
{
if(!use[i])
{
use[i] = 1;
w[x] = i;
dfs(x + 1);
use[i] = 0;
w[x] = 0;
}
}
}
int main()
{
scanf("%lld", &t);
for(int i = 1; i <= 3; ++i)
for(int j = 1; j <= 3; ++j)
{
int num = (i - 1) * 3 + j;
for(int k = 0; k < 4; ++k)
{
int tx = i + dx[k];
int ty = j + dy[k];
if(tx < 1 || tx > 3 || ty < 1 || ty > 3) continue;
p[num][(tx - 1) * 3 + ty] = 1;
}
p[num][num] = 1;
}
A.n = A.m = 9;
for(int i = 1; i <= 9; ++i)
for(int j = 1; j <= 9; ++j)
A.a[i][j] = p[i][j];
ksm(t);
for(int i = 1; i <= 9; ++i)
for(int j = 1; j <= 9; ++j)
f[i][j] = work(i, j);
dfs(1);
printf("%lld", Ans);
}