1. 程式人生 > >HihoCoder 1504 : 騎士遊歷 (矩陣乘法)

HihoCoder 1504 : 騎士遊歷 (矩陣乘法)

algo main %d i++ style span void end tor

描述

在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

此類題在Floyd算法裏用到過,即問從a出發,走x步,有多少種方法到b點。 充分利用floyd和矩陣的相似性(3個for語句),就可以求出。

很久沒有寫矩陣了,溫故一下。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=70;
#define ll long long
const int Mod=1e9+7;
int x[8]={2,2,-2,-2,1,1,-1,-1};
int y[8]={1,-1,1,-1,2,-2,2,-2};
struct
mat { ll M[maxn][maxn]; mat() { memset(M,0,sizeof(M)); } mat friend operator *(mat a,mat b) { mat res; for(int k=1;k<=64;k++) for(int i=1;i<=64;i++) for(int j=1;j<=64;j++){ res.M[i][j]=(res.M[i][j]+a.M[i][k]*b.M[k][j])%Mod; }
return res; } mat friend operator ^(mat a,int x) { mat res; for(int i=1;i<=64;i++) res.M[i][i]=1; while(x){ if(x&1) res=a*res; a=a*a; x/=2; } return res; } }; mat base; void prepare() { for(int i=1;i<=8;i++) for(int j=1;j<=8;j++) for(int k=0;k<8;k++) if(i+x[k]>=1&&i+x[k]<=8&&j+y[k]>=1&&j+y[k]<=8) base.M[(i-1)*8+j][(i+x[k]-1)*8+j+y[k]]=1; } int main() { int N,R,C,ans=0; scanf("%d%d%d",&N,&R,&C); prepare(); base=base^N; for(int i=1;i<=64;i++) ans=(ans+base.M[(R-1)*8+C][i])%Mod; printf("%d\n",ans); return 0; }

HihoCoder 1504 : 騎士遊歷 (矩陣乘法)