【[Offer收割]编程练习赛13 D】骑士游历(矩阵快速幂模板)
2017-04-15 22:29
489 查看
题目:http://hihocoder.com/problemset/problem/1504
题意:
描述在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的余数。
分析:
对于棋盘中任意一个点(R,C),都有多个位置可跳。比如:(R,C)可以跳到(R+1,C+2)的位置。
为了描述这种关系,可以建立一个64x64的邻接矩阵;这个邻接矩阵第一维对应8X8中的每一个点,第二维维护第一维的点可跳的位置。
对于这样的一个矩阵,用起始矩阵1X64乘以邻接矩阵64X64,得到的一个1X64的矩阵,这个矩阵的点上值表示从起始位置走一步,到达该位置有多少中方案。(参考离散数学和线性代数)
因此可以将这个乘以矩阵的过程转化为矩阵快速幂,迅速求得结果。
copy自:http://www.cnblogs.com/aiterator/p/6685932.html
话说用vector实现矩阵快速幂还挺清爽的,以后就这样用了。
代码:
#include<bits/stdc++.h> using namespace std; typedef vector<unsigned long long> vec; typedef vector<vec> mat; const unsigned long long mod = 1000000007; int dir[8][2] = { {1, 2}, {1, -2}, {-1, 2}, {-1, -2}, {2, 1}, {2, -1}, {-2, 1}, {-2, -1} }; mat mul(mat &a, mat &b) { mat c(a.size(), vec(b[0].size(), 0)); for(int i=0; i<a.size(); ++ i) { for(int j=0; j<b[0].size(); ++ j) { for(int k=0; k<b.size(); ++ k) c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod; } } return c; } mat pow(mat &a, unsigned long long n) { mat b(a.size(), vec(a[0].size(), 0)); for(int i=0; i<a.size(); ++ i) b[i][i] = 1; while(n > 0) { if(n & 1) b = mul(b, a); a = mul(a, a); n >>= 1; } return b; } int main() { int n, r, c; cin >> n >> r >> c; mat a(64, vec(64, 0)); for(int i=0; i<8; ++ i) { for(int j=0; j<8; ++ j) { for(int k=0; k<8; ++ k) { int x = i + dir[k][0], y = j + dir[k][1]; if((x >= 0 && x < 8 && y >= 0 && y < 8) == false) continue; int u = x * 8 + y, v = i * 8 + j; a[u][v] = a[v][u] = 1; } } } mat b(1, vec(64, 0)); b[0][(r-1)*8 + c-1] = 1; mat s = pow(a, n); mat d = mul(b, s); unsigned long long ans = 0; for(auto &i: d) { for(auto &j: i) ans = (ans + j) % mod; } cout << ans << endl; return 0; }
相关文章推荐
- 【[Offer收割]编程练习赛13 D】骑士游历(矩阵模板,乘法,加法,乘方)
- [Offer收割]编程练习赛13 hihocoder 1504 (矩阵快速幂)
- hihocoder offer收割编程练习赛13 D 骑士游历
- [Offer收割]编程练习赛13 B.最大子矩阵[枚举]
- 【[Offer收割]编程练习赛23 C】【矩阵快速幂】H国的身份证号码II
- 【[Offer收割]编程练习赛14 D】剑刃风暴(半径为R的圆能够覆盖的平面上最多点数目模板)
- 【[Offer收割]编程练习赛13 A】风格不统一如何写程序
- 【[Offer收割]编程练习赛13 C】 一人麻将
- 【hihocoder [Offer收割]编程练习赛9 D】【简单DP】矩阵填数
- HihoCoder1673 : 01间隔矩阵([Offer收割]编程练习赛41)(单调队列)
- 【[Offer收割]编程练习赛13 B】最大子矩阵(自己的思路)
- hiho 1615 矩阵游戏II [Offer收割]编程练习赛33 Problem A 贪心暴力
- 【[Offer收割]编程练习赛13 B】最大子矩阵(别人的思路)
- 【[Offer收割]编程练习赛9 D】 矩阵填数
- 时间模板【hihocoder [Offer收割]编程练习赛9 A】【模拟】闰秒
- 2016 [Offer收割]编程练习赛3 A B
- hihocoder[Offer收割]编程练习赛6及参考
- hihoCoder[Offer收割]编程练习赛1题目解析
- [Offer收割]编程练习赛7
- HiHoCoder [Offer收割]编程练习赛6 C. 图像算子(高斯消元小数版)