【插头DP】 ZOJ 3256 Tour in the Castle

通道:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3256

题意:简单路径-左上角走到左下角的路径方案数。

思路:M太大,需快速幂,预处理所有状态即可。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 
  5 using namespace std;
  6 
  7 const int maxn = 10001;
  8 const int MOD = 7777777;
  9 const int mov[10]={0,2,4,6,8,10,12,14,16};
 10 
 11 int n, m;
 12 int mp[2 << 16], res[130], tem[130], pos;
 13 bool vd[2 << 16];
 14 int A[6][30][130][130], B[130][130], len[6], sp[6][2];
 15 
 16 struct node {
 17     int size, head[maxn], next[maxn], sta[maxn];
 18     inline void clear() {
 19         memset(head, -1, sizeof head);
 20         size = 0;
 21     }
 22     inline void push(int st) {
 23         int hash = st % maxn;
 24         for (int i = head[hash]; ~i; i = next[i]) if (sta[i] == st) 
 25             return ;
 26         sta[size] = st; next[size] = hash;
 27         head[hash] = size++;
 28     }
 29 }dp[2];
 30 
 31 inline int getbit(int st, int k){return 3 & (st >> mov[k]); }
 32 inline int pybit(int st, int k){return st << mov[k]; }
 33 inline int clrbit(int st, int a, int b){return st & (~(3 << mov[a])) & (~(3 << mov[b])); }
 34 
 35 inline int fl(int st, int k, int n) {
 36     int cnt = 1;
 37     for(int i = k + 1; i <= n; ++i) {
 38         int e = getbit(st, i);
 39         if(e == 2) cnt--;
 40         else if(e == 1) cnt++;
 41         if(cnt == 0) return i;
 42     }
 43 }
 44 
 45 inline int fr(int st, int k) {
 46     int cnt = 1;
 47     for(int i = k - 1; i >= 0; --i) {
 48         int e = getbit(st, i);
 49         if(e == 2) cnt++;
 50         else if(e == 1) cnt--;
 51         if(cnt == 0) return i;
 52     }
 53 }
 54 
 55 inline int find(int st) {
 56     if(mp[st] == -1) mp[st] = pos++;
 57     return mp[st];
 58 }
 59 
 60 void bfs(int n) {
 61     queue<int > q;
 62     memset(vd, 0, sizeof vd);
 63     memset(mp, -1, sizeof mp);
 64     memset(B, 0, sizeof B);
 65     pos = 0;
 66     int in = pybit(1, 0) + pybit(2, n - 1);
 67     vd[in] = 1;
 68     q.push(in);
 69     while(!q.empty()) {
 70         int out = q.front(); q.pop();
 71         dp[0].clear();
 72         dp[0].push(out << 2);
 73         int now = 0, pre = 1;
 74         for(int j = 1; j <= n; ++j) {
 75             pre = now, now ^= 1; dp[now].clear();
 76             for (int k = 0; k < dp[pre].size; ++k) {
 77                 int l = getbit(dp[pre].sta[k], j - 1);
 78                 int up = getbit(dp[pre].sta[k], j);
 79                 int st = clrbit(dp[pre].sta[k], j - 1, j);
 80                 if(!l && !up) {
 81                     if(j < n) dp[now].push(st | pybit(1,j-1) | pybit(2,j));
 82                 } else if(!l || !up) {
 83                     int e = l == 0 ? up : l;
 84                     dp[now].push(st | pybit(e, j - 1));
 85                     if(j < n) dp[now].push(st | pybit(e, j));
 86                 } else if(l == 1 && up == 1) dp[now].push(st ^ pybit(3, fl(st, j, n)));
 87                 else if(l == 2 && up == 2) dp[now].push(st ^ pybit(3, fr(st, j - 1)));
 88                 else if(l == 2 && up == 1) dp[now].push(st);
 89                 else if(j == n && st == 0) ++B[find(out)][find(st)];
 90             }
 91         }
 92         for(int j = 0; j < dp[now].size; ++j) {
 93             in = dp[now].sta[j];
 94             if(!vd[in]) {
 95                 vd[in] = 1;
 96                 q.push(in);
 97             }
 98             ++B[find(out)][find(in)];
 99         }
100     }
101 }
102 
103 void init() {
104     for (int i = 0; i <= 5; ++i) {
105         bfs(i + 2);
106         len[i] = pos;
107         sp[i][0] = find(pybit(1, 0) + pybit(2, i + 1));
108         sp[i][1] = find(0);
109         for (int j = 0; j < len[i]; ++j) 
110             for (int k = 0; k < len[i]; ++k) 
111                 A[i][0][j][k] = B[j][k];
112         for (int j = 1; j < 30; ++j) {
113             for (int x = 0; x < len[i]; ++x) {
114                 for (int y = 0; y < len[i]; ++y) {
115                     for (int z = 0; z < len[i]; ++z) {
116                         long long t = (long long)(A[i][j - 1][x][z] * (long long)A[i][j - 1][z][y]);
117                         if(t >= MOD) t %= MOD;
118                         A[i][j][x][y] += t;
119                         if(A[i][j][x][y] >= MOD)  A[i][j][x][y] -= MOD;
120                     }
121                 }
122             }
123         }
124     }
125 }
126 
127 void Exp(int k, int e) {
128     int cnt = 0;
129     while(k > 0) {
130         if (k & 1) {
131             for (int j = 0; j < len[e]; ++j) {
132                 tem[j] = 0;
133                 for (int k = 0; k < len[e]; ++k) {
134                     long long t = (long long) res[k] * (long long)A[e][cnt][k][j];
135                     if (t >= MOD) t %= MOD;
136                     tem[j] += t;
137                     if (tem[j] >= MOD) tem[j] -= MOD;
138                 }
139             }
140             memcpy(res, tem, sizeof tem);
141         }
142         k >>= 1; ++cnt;
143     }
144 }
145 
146 int main() {
147     init();
148     while (2 == scanf("%d%d", &n, &m)) {
149         memset(res, 0, sizeof res);
150         res[sp[n - 2][0]] = 1;
151         Exp(m, n - 2);
152         if (res[sp[n - 2][1]] == 0) puts("Impossible");
153         else printf("%d\n", res[sp[n - 2][1]]);
154     }
155     return 0;
156 }
View Code

 

posted @ 2015-07-13 13:55  mithrilhan  阅读(179)  评论(0编辑  收藏  举报