After the final BOSS is defeated, the hero found that the whole castle is collapsing (very familiar scene, isn't it). Escape from the castle is easy, just need to cross a few rooms. But as the Hero is full of adventurous spirit, he decides to visit every room before he escape the castle.
The castle is a rectangle with N * M rooms in it. Two rooms are connected if they share a common edge. The hero starts in the top left room. And the bottom left room is the only way out. After the hero visits a room and leaves it, it will collapse immediately(Another familiar scene). So he can visit each room only once.
The diagram shows one tour over a castle with 4 * 10 rooms:
Input
There are multiply cases (<20), process to the end of file.
Each case contains a line with two Integer N and M (2 <= N <= 7, 1 <= M <=10^9).
Ouput
For each case, if it's impossible to visit every room exactly once and get to the bottom left room, output "Impossible". Otherwise, output the number of tours as it describe above. Beacause the answer can be huge, you just need to output the answer MOD 7777777.
Sample Input
3 2 3 3 4 10
Sample Output
Impossible 2 2329
Author: WANG, Yelei
Source: ZOJ Monthly, September 2009
看了几个大牛的博客。。基本上算是懂了。。
Codes:
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 using namespace std; 10 const int N = 1010; 11 const int Hash = 407; 12 const int Mod = 7777777; 13 #define For(i,n) for(int i=1;i<=n;i++) 14 #define Rep(i,l,r) for(int i=l;i<=r;i++) 15 #define Down(i,r,l) for(int i=r;i>=l;i--) 16 17 struct STATEDP{ 18 int size,st[N],head[Hash],next[N]; 19 void clear(){size=0;memset(head,-1,sizeof(head));} 20 int push(int state){ 21 int p,Key = state % Hash; 22 for(p = head[Key];p!=-1;p=next[p]) 23 if(st[p]==state) return p; 24 st[size]=state;next[size]=head[Key];head[Key]=size++; 25 return (size-1); 26 } 27 }dp; 28 29 struct Matrix{ 30 long long A[140][140]; 31 void clear(){memset(A,0,sizeof(A));} 32 }Unit,Ans; 33 34 int m,n,code[20]; 35 36 int encode(){ 37 int cnt=1 , h[20]; 38 memset(h,-1,sizeof(h));h[0]=0; 39 int st=0; 40 Rep(i,0,n-1){ 41 if(h[code[i]]==-1) h[code[i]]=cnt++; 42 code[i]=h[code[i]]; 43 st<<=2;st|=code[i]; 44 } 45 return st; 46 } 47 48 void decode(int st){ 49 Down(i,n-1,0) code[i] = st&3 , st>>=2; 50 } 51 52 void init(){ 53 Ans.clear();Unit.clear(); 54 dp.clear();dp.push(0); 55 memset(code,0,sizeof(code)); 56 code[0] = code[n-1] = 1; 57 dp.push(encode()); 58 } 59 60 Matrix operator *(Matrix A,Matrix B){ 61 Matrix C;C.clear(); 62 Rep(i,0,dp.size-1) 63 Rep(j,0,dp.size-1) 64 Rep(k,0,dp.size-1) 65 C.A[i][k]=(C.A[i][k] + (long long)(A.A[i][j] % Mod * B.A[j][k] % Mod)) % Mod; 66 return C; 67 } 68 69 void Quick(){ 70 while(m){ 71 if(m&1) Ans = Ans * Unit; 72 Unit = Unit * Unit; 73 m>>=1; 74 } 75 if(Ans.A[1][0]) printf("%lld ",Ans.A[1][0]); 76 else puts("Impossible"); 77 } 78 79 80 bool Check(int st,int nst){ 81 decode(st); 82 int up=0; 83 int cnt=0; 84 int k; 85 Rep(i,0,n-1){ 86 if(up==0){ 87 if(code[i]==0&&(nst&(1<<i))==0) return false; 88 if(code[i]&&(nst&(1<<i)))continue; 89 if(code[i]) up=code[i]; 90 else up=-1; 91 k=i; 92 } 93 else{ 94 if(code[i]&&(nst&(1<<i))) return false; 95 if(code[i]==0&&(nst&(1<<i))==0) continue; 96 if(code[i]){ 97 if(code[i]==up&&((nst!=0)||i!=n-1))return false; 98 if(up>0){ 99 Rep(j,0,n-1) 100 if(code[j]==code[i]&&j!=i) code[j]=code[k]; 101 code[i]=code[k]=0; 102 } 103 else{ 104 code[k]=code[i];code[i]=0; 105 } 106 } 107 else{ 108 if(up>0)code[i]=code[k],code[k]=0; 109 else code[i]=code[k]=n+(cnt++); 110 } 111 up=0; 112 } 113 } 114 if(up!=0)return false; 115 return true; 116 } 117 118 void DP(){ 119 For(i,dp.size-1) 120 Rep(j,0,(1<<n)) 121 if(Check(dp.st[i],j)) 122 Unit.A[i][dp.push(encode())] = 1; 123 Rep(i,0,dp.size) Ans.A[i][i] = 1; 124 Quick(); 125 } 126 127 int main(){ 128 while(~scanf("%d%d",&n,&m)){ 129 init(); 130 DP(); 131 } 132 return 0; 133 }