GYM 100827 F.Knights(dp+矩阵快速幂)
2017-03-09 15:08
253 查看
Description
一个m*n棋盘,可以在上面放若干马,问有多少中放法使得马之间不会互相冲突
Input
第一行一整数T表示用例组数,每组用例输入两个整数m和n分别表示棋盘的行列数(1<=T<=10,1<=m<=4,1<=n<=1e9)
Output
对于每组用例输出合法方案数
Sample Input
4
1 2
2 2
3 2
4 31415926
Sample Output
4
16
36
413011760
Solution
在第i列放马只会影响第i+1和i+2列(前面的列不会影响,因为这个位置能放马说明没有被前面的影响到 ),那么只要推出i,i+1两列到i+1,i+2两列的状态转移矩阵再矩阵快速幂即可,状态转移矩阵也比较好推,三列只有至多十二个位置,4096种状态,每次看i,i+1这两列的状态x是否能够转移到i+1,i+2这两列的状态y,只需要把这三行的马放好之后判断即可,合法那么A[x][y]=1,否则A[x][y]=0
Code
一个m*n棋盘,可以在上面放若干马,问有多少中放法使得马之间不会互相冲突
Input
第一行一整数T表示用例组数,每组用例输入两个整数m和n分别表示棋盘的行列数(1<=T<=10,1<=m<=4,1<=n<=1e9)
Output
对于每组用例输出合法方案数
Sample Input
4
1 2
2 2
3 2
4 31415926
Sample Output
4
16
36
413011760
Solution
在第i列放马只会影响第i+1和i+2列(前面的列不会影响,因为这个位置能放马说明没有被前面的影响到 ),那么只要推出i,i+1两列到i+1,i+2两列的状态转移矩阵再矩阵快速幂即可,状态转移矩阵也比较好推,三列只有至多十二个位置,4096种状态,每次看i,i+1这两列的状态x是否能够转移到i+1,i+2这两列的状态y,只需要把这三行的马放好之后判断即可,合法那么A[x][y]=1,否则A[x][y]=0
Code
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; #define maxn 256 #define mod 1000000009ll struct Mat { int mat[maxn][maxn];//矩阵 int row,col;//矩阵行列数 }; Mat mod_mul(Mat a,Mat b,ll p)//矩阵乘法 { Mat ans; ans.row=a.row; ans.col=b.col; memset(ans.mat,0,sizeof(ans.mat)); for(int i=0;i<ans.row;i++) for(int k=0;k<a.col;k++) if(a.mat[i][k]) for(int j=0;j<ans.col;j++) { ans.mat[i][j]+=1ll*a.mat[i][k]*b.mat[k][j]%p; ans.mat[i][j]%=p; } return ans; } Mat mod_pow(Mat a,int k,ll p)//矩阵快速幂 { Mat ans; ans.row=a.row; ans.col=a.col; for(int i=0;i<a.row;i++) for(int j=0;j<a.col;j++) ans.mat[i][j]=(i==j); while(k) { if(k&1)ans=mod_mul(ans,a,p); a=mod_mul(a,a,p); k>>=1; } return ans; } int T,n,m,a[5][5]; void deal(int x) { for(int i=0;i<3*m;i++) if(x&(1<<i))a[i/m][i%m]=1; else a[i/m][i%m]=0; } int dx[]={-2,-2,-1,-1,1,1,2,2}; int dy[]={-1,1,-2,2,-2,2,-1,1}; bool check() { for(int i=0;i<3;i++) for(int j=0;j<m;j++) if(a[i][j]) for(int k=0;k<8;k++) { int ii=i+dx[k],jj=j+dy[k]; if(ii<0||ii>=3||jj<0||jj>=m)continue; if(a[ii][jj])return 0; } return 1; } Mat A,B; int main() { scanf("%d",&T); while(T--) { scanf("%d%d",&m,&n); if(n==1) { printf("%d\n",1<<m); continue; } int M=1<<(2*m),N=1<<(3*m); B.row=M,B.col=1; for(int i=0;i<M;i++) { deal(i); B.mat[i][0]=check(); } A.row=A.col=M; memset(A.mat,0,sizeof(A.mat)); for(int i=0;i<N;i++) { int x=i>>m,y=i&(M-1); deal(i); if(check())A.mat[x][y]=1; } A=mod_pow(A,n-2,mod); A=mod_mul(A,B,mod); ll ans=0; for(int i=0;i<M;i++)ans=(ans+A.mat[i][0])%mod; printf("%I64d\n",ans); } return 0; }
相关文章推荐
- [CF Gym 100827F] Knights [2014-2015 ACM-ICPC Pacific Northwest Regional Contest F]
- GYM 100827 D.Function(高斯消元)
- GYM 100827 G.Number Game(博弈论)
- GYM 101061 B.RGB plants(dp+矩阵快速幂)
- Codeforces Gym 100650D Queens, Knights and Pawns 暴力
- GYM 100827 E.Hill Number(数位DP)
- GYM 100827 H.Pushups(01背包)
- GYM 100827 I.Salary Inequity(线段树)
- codeforces gym 2016-2017 NEERC, Moscow Subregional K. Knights of the Old Republic 最小生成树+dp
- GYM 100827 K.Towers(dfs)
- GYM 100827 L.Wormhole(Floyd)
- GYM 101061 G.Repeat it(dp+矩阵快速幂)
- Codeforces Gym 100650D Queens, Knights and Pawns 暴力
- [CF Gym 100827C] Containment [2014-2015 ACM-ICPC Pacific Northwest Regional Contest C]
- [CF Gym 100827E] Hill Number [2014-2015 ACM-ICPC Pacific Northwest Regional Contest E]
- 【codeforces】gym 101137 K - Knights of the Old Republic【用最小生成树对图做集合dp】
- GYM 100827 A.Runes(水~)
- Gym - 101350G Snake Rana
- Binary Strings Gym - 101161G 矩阵快速幂 + 打表
- codeforce GYM 100741 A Queries