HihoCoder 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的余数。
样例输入
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; }
It is your time to fight!