[Offer收割]编程练习赛13 hihocoder 1504 (矩阵快速幂)

来源:互联网 发布:安徽省癌症数据 编辑:程序博客网 时间:2024/05/29 16:39

#1504 : 骑士游历

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

在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的余数。

样例输入
2 1 1
样例输出
12

题目链接: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);    }}



0 0