时间限制:
10000ms 单点时限:
1000ms 内存限制:
256MB
描述
在8×8的国际象棋棋盘上给定一只骑士(俗称“马”)棋子的位置(R, C),小Hi想知道从(R, C)开始移动N步一共有多少种不同的走法。
输入
第一行包含三个整数,N,R和C。
对于40%的数据, 1 <= N <= 1000000
对于100%的数据, 1 <= N <= 1000000000 1 <= R, C <= 8
输出
从(R, C)开始走N步有多少种不同的走法。由于答案可能非常大,你只需要输出答案模1000000007的余数。
暴力一点把8X8的棋盘展开
那么每一个 1X64的矩阵代表的是 这个8X8的棋盘里 哪些点会对当前点有共享
预处理一下关系转移矩阵
初始化一下,然后矩阵快速幂即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int size = 255;
int dx[] = { -1, 1, -2, 2, -2, 2, -1, 1 };
int dy[] = { -2, -2, -1, -1, 1, 1, 2, 2 };
const int N = 64+6;
const long long mod=1e9+7;
struct Matrix
{
long long mat[N][N];
} ;
Matrix unit_matrix ;
vector<int> son[64+5];
const int k=64;
Matrix mul(Matrix a, Matrix b) //矩阵相乘
{
Matrix res;
for(int i = 0; i < k; i++)
for(int j = 0; j < k; j++)
{
res.mat[i][j] = 0;
for(int t = 0; t < k; t++)
{
res.mat[i][j] += a.mat[i][t] * b.mat[t][j];
res.mat[i][j] %= mod;
}
}
return res;
}
Matrix pow_matrix(Matrix a, long long m) //矩阵快速幂
{
Matrix res = unit_matrix;
while(m != 0)
{
if(m & 1)
res = mul(res, a);
a = mul(a, a);
m >>= 1;
}
return res;
}
Matrix get(long long n,long long r,long long cc)
{
Matrix ori;
memset( ori.mat ,0,sizeof ori.mat);
ori.mat[0][r*8+cc]=1;
Matrix c;
memset( c.mat ,0,sizeof c.mat);
for(int j=0; j<64; j++)
for(int i=0; i<son[j].size(); i++)
c.mat[ son[j][i] ][j]=1;
Matrix ans = pow_matrix(c, n);
ans= mul(ori,ans);
return ans;
}
void pre()
{
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
for(int k=0; k<8; k++)
{
int xx=i+dx[k];
int yy=j+dy[k];
if (xx>=0&&xx<8&&yy>=0&&yy<8)
{
son[i*8+j].push_back(xx*8+yy);
}
}
}
}
}
int main()
{
pre();
//初始化单位矩阵 //类似快速幂的 ans=1; 如今是ans=单位矩阵
memset(unit_matrix.mat,0,sizeof unit_matrix.mat);
for(int i = 0; i < k; i++) unit_matrix.mat[i][i] = 1;
int n,r,c;
scanf("%d%d%d",&n,&r,&c);
Matrix ans=get(n,r-1,c-1);
ll sum=0;
for(int i=0;i<64;i++)
sum=(sum+ans.mat[0][i])%mod;
printf("%lld\n",sum);
return 0;
}