由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移。
这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态。
进行两遍bfs,分别为初始状态可以到达的状态,和可以到达终止状态的状态。
同时出现在两次bfs中的状态即为有效状态,一共有141种。
这样就可以跑出来了。
未加矩阵快速幂 50分
1 const dx:array[1..8,1..3] of longint= 2 ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1)); 3 dy:array[1..8,1..3] of longint= 4 ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0)); 5 mo=65521; 6 var n,m,lx,i,j,k:longint; 7 a:array[0..10,0..10] of longint; 8 g:array[0..5000,0..5000] of longint; 9 dp:array[0..200,0..5000] of longint; 10 function ok(x,y:longint):boolean; inline; 11 begin 12 if (x>=1) and (x<=3) and (y>=1) and (y<=m) and (a[x,y]=0) then exit(true); 13 exit(false); 14 end; 15 function check(y,j:longint):boolean; 16 var i,x:longint; 17 begin 18 x:=2; 19 if not ok(x,y) then exit(false); 20 for i:=1 to 3 do 21 if not ok(x+dx[j,i],y+dy[j,i]) then exit(false); 22 exit(true); 23 end; 24 procedure fill(y,j,cl:longint); 25 var i,x:longint; 26 begin 27 x:=2; 28 a[x,y]:=cl; 29 for i:=1 to 3 do 30 a[x+dx[j,i],y+dy[j,i]]:=cl; 31 end; 32 procedure dfs(x,lt:longint); 33 var i,j,sum:longint; 34 begin 35 if x=m+1 then 36 begin 37 for i:=1 to m do if a[1,i]=0 then exit; //保证了DP的正确性 38 sum:=0; 39 for i:=2 to 3 do 40 for j:=1 to m do 41 sum:=sum*2+a[i,j]; 42 inc(g[lt][sum]); 43 exit; 44 end; 45 dfs(x+1,lt); 46 for i:=1 to 8 do 47 if check(x,i) then 48 begin 49 fill(x,i,1); 50 dfs(x+1,lt); 51 fill(x,i,0); 52 end; 53 end; 54 begin 55 assign(input,'tile.in');reset(input); 56 assign(output,'tile.out');rewrite(output); 57 readln(n,m); 58 for i:=0 to 1<<(2*m)-1 do 59 begin 60 for j:=1 to m do 61 if i and (1<<(m*2-j))>0 then a[1,j]:=1 else a[1,j]:=0; 62 for j:=1 to m do 63 if i and (1<<(m-j))>0 then a[2,j]:=1 else a[2,j]:=0; 64 dfs(1,i); 65 end; 66 dp[1][(1<<m-1)<<m]:=1; 67 for i:=2 to n+1 do 68 for j:=0 to 1<<(2*m)-1 do 69 for k:=0 to 1<<(2*m)-1 do 70 dp[i][j]:=(dp[i][j]+dp[i-1][k]*g[k][j]) mod mo; 71 writeln(dp[n+1][(1<<m-1)<<m]); 72 close(input); 73 close(output); 74 end.
AC 代码1:
1 const dx:array[1..8,1..3] of longint= 2 ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1)); 3 dy:array[1..8,1..3] of longint= 4 ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0)); 5 mo=65521; 6 type arr=array[0..500,0..500] of int64; 7 var i,j,k,m,xh:longint; 8 n:int64; 9 a:array[0..100,0..100] of longint; 10 g:array[0..4200,0..4200] of longint; 11 b:array[0..100000] of longint; 12 v1,v2:array[0..4200] of boolean; 13 pos:array[0..4200] of int64; 14 mat,f:arr; 15 function ok(x,y:longint):boolean; inline; 16 begin 17 if (y>=1) and (y<=m) and (a[x,y]=0) then exit(true); 18 exit(false); 19 end; 20 function check(y,j:longint):boolean; inline; 21 var i,x:longint; 22 begin 23 x:=2; 24 if not ok(x,y) then exit(false); 25 for i:=1 to 3 do 26 if not ok(x+dx[j,i],y+dy[j,i]) then exit(false); 27 exit(true); 28 end; 29 procedure fill(y,j,cl:longint); inline; 30 var i,x:longint; 31 begin 32 x:=2; 33 a[x,y]:=cl; 34 for i:=1 to 3 do 35 a[x+dx[j,i],y+dy[j,i]]:=cl; 36 end; 37 procedure dfs(x,lt:longint); 38 var i,j,sum:longint; 39 begin 40 if x=m+1 then 41 begin 42 for i:=1 to m do if a[1,i]=0 then exit; 43 sum:=0; 44 for i:=2 to 3 do 45 for j:=1 to m do 46 sum:=sum*2+a[i,j]; 47 inc(g[lt][sum]); 48 exit; 49 end; 50 dfs(x+1,lt); 51 for i:=1 to 8 do 52 if check(x,i) then 53 begin 54 fill(x,i,1); 55 dfs(x+1,lt); 56 fill(x,i,0); 57 end; 58 end; 59 procedure bfs; 60 var i,j,l,r,x,y:longint; 61 begin 62 fillchar(v1,sizeof(v1),false); 63 fillchar(v2,sizeof(v2),false); 64 l:=1; r:=1; b[1]:=(1<<m-1)<<m; v1[(1<<m-1)<<m]:=true; 65 while l<=r do 66 begin 67 x:=b[l]; 68 for y:=0 to (1<<(m*2)-1) do 69 if (g[x,y]>0) and not v1[y] then 70 begin 71 v1[y]:=true; 72 inc(r); 73 b[r]:=y; 74 end; 75 inc(l); 76 end; 77 l:=1; r:=1; b[1]:=(1<<m-1)<<m; v2[(1<<m-1)<<m]:=true; 78 while l<=r do 79 begin 80 x:=b[l]; 81 for y:=0 to 1<<(m*2)-1 do 82 if (g[y,x]>0) and not v2[y] then 83 begin 84 v2[y]:=true; 85 inc(r); 86 b[r]:=y; 87 end; 88 inc(l); 89 end; 90 xh:=0; 91 for i:=0 to 1<<(m*2)-1 do 92 if v1[i] and v2[i] then 93 begin 94 inc(xh); 95 pos[i]:=xh; 96 end; 97 for i:=1 to r do 98 for j:=1 to r do 99 mat[pos[b[i]],pos[b[j]]]:=g[b[i],b[j]]; 100 end; 101 operator *(a,b:arr) c:arr; inline; 102 var i,j,k:longint; 103 begin 104 for i:=1 to xh do 105 for j:=1 to xh do 106 begin 107 c[i,j]:=0; 108 for k:=1 to xh do 109 c[i,j]:=(c[i,j]+a[i,k]*b[k,j]); 110 c[i,j]:=c[i,j] mod mo; 111 end; 112 exit(c); 113 end; 114 begin 115 assign(input,'tile.in');reset(input); 116 assign(output,'tile.out');rewrite(output); 117 readln(n,m); 118 for i:=0 to 1<<(2*m)-1 do 119 begin 120 for j:=1 to m do 121 if i and (1<<(m*2-j))>0 then a[1,j]:=1 else a[1,j]:=0; 122 for j:=1 to m do 123 if i and (1<<(m-j))>0 then a[2,j]:=1 else a[2,j]:=0; 124 dfs(1,i); 125 end; 126 {dp[1][(1<<m-1)<<m]:=1; 127 for i:=2 to n+1 do 128 for j:=0 to 1<<(2*m)-1 do 129 for k:=0 to 1<<(2*m)-1 do 130 dp[i][j]:=(dp[i][j]+dp[i-1][k]*g[k][j]) mod mo;} 131 bfs; 132 for i:=1 to xh do f[i,i]:=1; 133 writeln(xh); 134 while n>0 do 135 begin 136 if n and 1=1 then f:=f*mat; 137 mat:=mat*mat; 138 n:=n>>1; 139 end; 140 writeln(f[pos[(1<<m-1)<<m]][pos[(1<<m-1)<<m]]); 141 close(input); 142 close(output); 143 end.
AC 代码2 :(Orz rpCardinal)
1 #include <cstdio> 2 #include <cstring> 3 #define P 65521 4 5 #ifdef _WIN32 6 #define ll "%I64d" 7 #else 8 #define ll "%lld" 9 #endif 10 11 int m,M,ST,N,q[5000],h[5000],pos[5000]; 12 long long n,g[4096][4096],t[150][150]; 13 bool b[3][10],v1[5000],v2[5000]; 14 15 struct matrix 16 { 17 long long a[150][150]; 18 matrix() {memset(a,0,sizeof(a));} 19 void one() {for (int i=1;i<=N;++i) a[i][i]=1;} 20 matrix& operator*=(const matrix &B) 21 { 22 memset(t,0,sizeof(t)); 23 for (int i=1;i<=N;++i) 24 for (int j=1;j<=N;++j) 25 for (int k=1;k<=N;++k) 26 t[i][j]=(t[i][j]+a[i][k]*B.a[k][j])%P; 27 memcpy(a,t,sizeof(a)); return *this; 28 } 29 }A,R; 30 31 bool can(int i,int j) 32 {return i>=0&&i<3&&j>=0&&j<m&&!b[i][j];} 33 34 bool check(int k,int i) 35 { 36 switch (k) 37 { 38 case 1:return can(1,i)&&can(1,i+1)&&can(0,i); 39 case 2:return can(1,i)&&can(1,i+1)&&can(2,i); 40 case 3:return can(1,i)&&can(1,i-1)&&can(2,i); 41 case 4:return can(1,i)&&can(1,i-1)&&can(0,i); 42 case 5:return can(1,i)&&can(0,i)&&can(2,i)&&can(1,i+1); 43 case 6:return can(1,i)&&can(2,i)&&can(1,i-1)&&can(1,i+1); 44 case 7:return can(1,i)&&can(0,i)&&can(2,i)&&can(1,i-1); 45 case 8:return can(1,i)&&can(0,i)&&can(1,i-1)&&can(1,i+1); 46 default:return 0; 47 } 48 } 49 50 bool fill(int k,int i,int v) 51 { 52 switch (k) 53 { 54 case 1:return b[1][i]=b[1][i+1]=b[0][i]=v; 55 case 2:return b[1][i]=b[1][i+1]=b[2][i]=v; 56 case 3:return b[1][i]=b[1][i-1]=b[2][i]=v; 57 case 4:return b[1][i]=b[1][i-1]=b[0][i]=v; 58 case 5:return b[1][i]=b[0][i]=b[2][i]=b[1][i+1]=v; 59 case 6:return b[1][i]=b[2][i]=b[1][i-1]=b[1][i+1]=v; 60 case 7:return b[1][i]=b[0][i]=b[2][i]=b[1][i-1]=v; 61 case 8:return b[1][i]=b[0][i]=b[1][i-1]=b[1][i+1]=v; 62 default:return 0; 63 } 64 } 65 66 void dfs(int dep,int last) 67 { 68 if (dep>m) 69 { 70 for (int i=0;i<m;++i) if (!b[0][i]) return; 71 int next=0; 72 for (int i=2;i;--i) 73 for (int j=m-1;j>=0;--j) 74 next=next*2+b[i][j]; 75 ++g[last][next]; return; 76 } 77 dfs(dep+1,last); 78 for (int i=1;i<=8;++i) 79 if (check(i,dep)) 80 {fill(i,dep,1); dfs(dep+1,last); fill(i,dep,0);} 81 } 82 83 void bfs() 84 { 85 int l=0,r=0; q[++r]=ST; v1[ST]=1; 86 while (l<r) 87 { 88 int x=q[++l]; 89 for (int y=0;y<M;++y) 90 if (g[x][y]&&!v1[y]) {v1[y]=1; q[++r]=y;} 91 } 92 l=r=0; q[++r]=ST; v2[ST]=1; 93 while (l<r) 94 { 95 int x=q[++l]; 96 for (int y=0;y<M;++y) 97 if (g[y][x]&&!v2[y]) {v2[y]=1; q[++r]=y;} 98 } 99 for (int i=0;i<M;++i) 100 if (v1[i]&&v2[i]) {h[++N]=i; pos[i]=N;} 101 for (int i=0;i<M;++i) 102 for (int j=0;j<M;++j) 103 A.a[pos[i]][pos[j]]=g[i][j]; 104 } 105 106 void pow(long long b) 107 {while (b) {if (b&1) R*=A; A*=A; b>>=1;}} 108 109 int main() 110 { 111 freopen("tile.in","r",stdin); 112 freopen("tile.out","w",stdout); 113 scanf(ll "%d",&n,&m); M=1<<(2*m); ST=(1<<m)-1; 114 for (int st=0;st<M;++st) 115 { 116 for (int i=0;i<m;++i) b[0][i]=(st>>i)&1; 117 for (int i=0;i<m;++i) b[1][i]=(st>>(i+m))&1; 118 dfs(0,st); 119 } 120 bfs(); R.one(); pow(n); 121 printf(ll " ",R.a[pos[ST]][pos[ST]]); 122 fclose(stdin); fclose(stdout); 123 return 0; 124 }