您的位置:首页 > 大数据 > 人工智能

2016 Multi-University Training Contest 1 I. Solid Dominoes Tilings

2016-08-28 20:23 225 查看

Solid Dominoes Tilings

Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 235 Accepted Submission(s): 143


[align=left]Problem Description[/align]
Dominoes are rectangular tiles with nice 2 × 1 and 1 × 2 sizes.

The tiling is called solid if it is not possible to split the tiled rectangle by a straight line, not crossing the interior of any tile. For example, on the picture below the tilings (a) and (b) are solid, while the tilings (c) and (d) are not.

const int N = 18, M = 2000010, MOD = 1e9 + 7;
int head[1 << N], son[M], nex[M], tot;
int ans

, blocks
;
int width;
int G
[1 << N], g

;

inline int add(int x, int y) {
return ((x + y) % MOD + MOD) % MOD;
}

inline int mul(int x, int y) {
return ((x * 1ll * y) % MOD + MOD) % MOD;
}

inline void addEdge(int u, int v) {
son[tot] = v, nex[tot] = head[u];
head[u] = tot++;
}

inline void searchNexState(int goalState, int nowState, int d) {
if(d == width) addEdge(goalState, nowState);
else if((goalState >> d) & 1) {
if(d < width - 1 && (goalState >> (d + 1) & 1)) {
int nexState = nowState;
nexState |= (1 << d) | (1 << (d + 1));
searchNexState(goalState, nexState, d + 2);
}
searchNexState(goalState, nowState, d + 1);
} else searchNexState(goalState, nowState | (1 << d), d + 1);
}

inline void getTransfer(int n) {
width = n, tot = 0;
for(int i = 0; i < (1 << n); ++i) {
head[i] = -1;
searchNexState(i, 0, 0);
}
// printf("%d\n", tot);
}

inline void getG(int n, int m) {
for(int tab = head[(1 << m) - 1]; tab != -1; tab = nex[tab])
G[1][son[tab]] = 1;
for(int i = 1; i < n; ++i) {
for(int u = 0; u < (1 << m); ++u) G[i + 1][u] = 0;
for(int u = 0; u < (1 << m); ++u) {
if(G[i][u]) {
for(int tab = head[u]; tab != -1; tab = nex[tab])
G[i + 1][son[tab]] = add(G[i + 1][son[tab]], G[i][u]);
}
}
}
for(int i = 1; i <= n; ++i) g[i][m] = G[i][(1 << m) - 1];
}

inline void search(int w, int now, int len) {
if(w >= width) {
blocks[len++] = now;
static int F
, G
;
for(int n = 1; n <= 16; ++n) {
int cnt = 1;
for(int i = 0; i < len; ++i) cnt = mul(cnt, g
[blocks[i]]);
F
= G
= cnt;
for(int h = 1; h < n; ++h)
F
= add(F
, -mul(F[h], G[n - h]));
if(len & 1) ans
[width] = add(ans
[width], F
);
else ans
[width] = add(ans
[width], -F
);
}
} else {
search(w + 1, now + 1, len);
blocks[len] = now;
search(w + 1, 1, len + 1);
}
}

inline void init() {
for(int m = 1; m <= 16; ++m) {
width = m;
getTransfer(m);
getG(16, m);
search(1, 1, 0);
}
}

int n, m;
int main() {
init();
while(scanf("%d%d", &n, &m) == 2) printf("%d\n", ans
[m]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐