#1504 : 骑士游历
时间限制:
10000ms
单点时限:
1000ms
内存限制:
256MB
-
2 1 1
样例输出
-
12
描述
在8x8的国际象棋棋盘上给定一只骑士(俗称“马”)棋子的位置(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的余数。
题目链接:https://hihocoder.com/problemset/problem/1504
题目分析:典型的矩阵快速幂问题,由于棋盘大小只有8*8,可以将一个点的横纵坐标hash成一个值,建一个64*64的矩阵来表示点的转移
import java.util.*;
import java.io.*;
public class Main {
public static final long MOD = 1000000007;
public static final int CON = 64;
public static int[] dx = {1, 2, 2, 1, -1, -2, -2, -1};
public static int[] dy = {-2, -1, 1, 2, 2, 1, -1, -2};
public static int n, r, c;
static class myScanner {
public BufferedReader br;
public StringTokenizer st;
public myScanner(InputStream in) {
br = new BufferedReader(new InputStreamReader(in));
st = new StringTokenizer("");
}
public String nextLine() {
try {
return br.readLine();
} catch(IOException e) {
return null;
}
}
public boolean hasNext() {
while(!st.hasMoreTokens()) {
String s = nextLine();
if (s == null) {
return false;
}
st = new StringTokenizer(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
}
static class Matrix {
public int n, m;
public long[][] mat;
public Matrix(int n, int m) {
this.n = n;
this.m = n;
mat = new long[n][m];
for (int i = 0; i < n; i ++) {
Arrays.fill(mat[i], 0);
}
}
public static Matrix mul(Matrix a, Matrix b) {
Matrix ans = new Matrix(a.n, b.m);
for (int i = 0; i < a.n; i ++) {
for (int j = 0; j < b.m; j ++) {
for (int k = 0; k < a.m; k ++) {
ans.mat[i][j] = (ans.mat[i][j] + a.mat[i][k] * b.mat[k][j]) % MOD;
}
}
}
return ans;
}
public static Matrix pow(Matrix a, int n) {
Matrix ans = new Matrix(a.n, a.n);
for (int i = 0; i < a.n; i ++) {
ans.mat[i][i] = 1;
}
while (n != 0) {
if ((n & 1) == 1) {
ans = mul(ans, a);
}
a = mul(a, a);
n >>= 1;
}
return ans;
}
}
public static Matrix pre() {
Matrix ans = new Matrix(64, 64);
for (int i = 0; i < 8; i ++) {
for (int j = 0; j < 8; j ++) {
for (int k = 0; k < 8; k ++) {
int x = i + dx[k];
int y = j + dy[k];
if (x < 0 || y < 0 || x > 7 || y > 7) {
continue;
}
ans.mat[i * 8 + j][x * 8 + y] = 1;
}
}
}
return ans;
}
public static void main(String[] args) {
myScanner in = new myScanner(System.in);
n = in.nextInt();
r = in.nextInt();
c = in.nextInt();
r --;
c --;
Matrix coef = pre();
Matrix ans = new Matrix(64, 64);
ans.mat[r * 8 + c][r * 8 + c] = 1;
ans = Matrix.mul(ans, Matrix.pow(coef, n));
long res = 0;
for (int i = 0; i < 64; i ++) {
for (int j = 0; j < 64; j ++) {
res = (res + ans.mat[i][j]) % MOD;
}
}
System.out.println(res);
}
}