未加矩阵快速幂 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 #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 "\n",R.a[pos[ST]][pos[ST]]); 122 fclose(stdin); fclose(stdout); 123 return 0; 124 }
时间: 2024-11-23 21:59:02