链接:https://ac.nowcoder.com/acm/contest/554/D
来源:牛客网
题目描述
wkroach明天终于要去和那个女孩见面了,这天晚上在梦中他变成了一名骑士,然而wkroach毕竟是理工男,他变成的是棋盘上骑士,在梦醒之前他有N步移动的机会,wkroach想知道他总共可能有多少种走法呢。
这是一个8*8的棋盘,wkroach有一个初始位置,每次移动不能超出棋盘并且必须遵循骑士行走的规则也就和中国象棋的“马”类似但是不存在“蹩马腿”,如果你二者的规则都不知道那就看下一题吧)
输入描述:
第一行输入一个正整数T代表测试样例数目 每组样例有三个正整数N R C(0<n<1000000000,0<R<9,0<C<9)代表此样例步数N及wkroach的初始点(R,C)。
输出描述:
对于每组测试数据,输出一个整数,表示总走法数。
思路:定义a[i][j]为地图,第i,j表示位置,给每个位置付一个值,然后定义64*64的矩阵,将i,j,能到达的位置放进vector里。
算了,具体看代码。
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define mem(ar,num) memset(ar,num,sizeof(ar))
#define me(ar) memset(ar,0,sizeof(ar))
#define lowbit(x) (x&(-x))
#define IOS ios::sync_with_stdio(false)
#define DEBUG cout<<endl<<"DEBUG"<<endl;
using namespace std;
const int mod = 1e9 + 7;
ll t, n, r, c;
struct mtx {
ll x[64 + 1][64 + 1];
mtx() {
memset(x, 0, sizeof x);
}
} ans;
mtx operator *(const mtx &a, const mtx &b) {
mtx c;
for(int i = 0; i < 64; i++)
for(int j = 0; j < 64; j++)
for(int k = 0; k < 64; k++)
c.x[i][j] = (c.x[i][j] + a.x[i][k] * b.x[k][j] % mod) % mod;
return c;
}
mtx operator ^(mtx a, ll k) {
mtx ret;
for(int i = 0; i < 64; ++i)
ret.x[i][i] = 1;
while(k) {
if(k & 1)
ret = ret * a;
a = a * a;
k >>= 1;
}
return ret;
}
int o[9][9], bb;
vector<int>v[100];
int main() {
cin >> t;
for(int i = 0; i < 8; i++)
for(int j = 0; j < 8; j++)
o[i][j] = bb++;
for(int i = 0; i < 8; i++) {
for(int j = 0; j < 8; j++) {
int k = o[i][j];
if((i + 2) < 8 && (j + 1) < 8)
v[k].push_back(o[i + 2][j + 1]);
if((i + 1) < 8 && (j + 2) < 8)
v[k].push_back(o[i + 1][j + 2]);
if((i - 1) >= 0 && (j - 2) >= 0)
v[k].push_back(o[i - 1][j - 2]);
if((i - 2) >= 0 && (j - 1) >= 0)
v[k].push_back(o[i - 2][j - 1]);
if((i - 2) >= 0 && (j + 1) < 8)
v[k].push_back(o[i - 2][j + 1]);
if((i - 1) >= 0 && (j + 2) < 8)
v[k].push_back(o[i - 1][j + 2]);
if((i + 1) < 8 && (j - 2) >= 0)
v[k].push_back(o[i + 1][j - 2]);
if((i + 2) < 8 && (j - 1) >= 0)
v[k].push_back(o[i + 2][j - 1]);
}
}
while(t--) {
cin >> n >> r >> c;
mtx ak;
for(int i = 0; i < 64; i++)
for(int j = 0; j < v[i].size(); j++)
ak.x[i][v[i][j]] = 1;
int ans = 0;
mtx w = ak ^ n;//走n步
int k = o[r-1][c-1];//记得减一,debug好久
for(int i = 0; i < 64; i++) {
ans += w.x[k][i];//将k能到达的位置加起来。
ans %= mod;
}
cout << ans << endl;
}
return 0;
}