首页 > 代码库 > POJ3420 Quad Tiling DP + 矩阵快速幂
POJ3420 Quad Tiling DP + 矩阵快速幂
题目大意是用1*2的骨牌堆积成4*N的矩形,一共有多少种方法,N不超过10^9。
这题和曾经在庞果网上做过的一道木块砌墙几乎一样。因为骨牌我们可以横着放,竖着放,我们假设以4为列,N为行这样去看,并且在骨牌覆盖的位置上置1,所以一共最多有16种状态。我们在第M行放骨牌的时候,第M+1行的状态也是有可能被改变的,设S(i,j)表示某一行状态为i时,将其铺满后下一行状态为j的方案书。考虑下如果我们让矩阵S和S相乘会有什么意义,考虑一下会发现S*S的意义当某行状态为i,接着其后面第2行的状态为j的可行方案数,一般地,S^n则代表接下来第n行状态为j的方案数,这里N很大,我们可以用快速幂对矩阵的幂进行加速。对于S矩阵的最初状态我们可以穷尽搜索来求。
#include <stdlib.h> #include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string> #include <iostream> #include <queue> #include <list> #include <algorithm> #include <stack> #include <map> #include<iostream> #include<cstdio> using namespace std; int State[16][16]; int Start[16][16]; int IMod; void InitState(int ori, int s, int p) { bool isfull = true; for (int i = 0; i < 4; i++) { if (((s >> i) & 1) == 0) { //竖着放 InitState(ori, s | (1 << i), p | (1 << i)); //横着放 if (i < 3 && ((s >> (i + 1)) & 1) == 0) { int tp = s | (1 << i); tp |= (1 << (i + 1)); InitState(ori ,tp, p); } isfull = false; break; } } if (isfull) { State[ori][p] += 1; } } void Product(int a[][16], int b[][16], int res[][16]) { for (int i = 0; i < 16;i++) { for (int j = 0; j < 16; j++) { res[i][j] = 0; for (int k = 0; k < 16; k++) { res[i][j] += (a[i][k] * b[k][j] % IMod); res[i][j] %= IMod; } } } } void QProduct(int p[][16], int res[16][16], int n) { memset(res, 0, sizeof(int) * 16 * 16); int tmp[2][16][16]; int tmpres[16][16]; memcpy(tmp[0], p, sizeof(int) * 16 * 16); int i = 0; for (int k = 0; k < 16; k++) { res[k][k] = 1; } while (n) { if (n & 1) { memcpy(tmpres, res, sizeof(int) * 16 * 16); Product(tmpres, tmp[i & 1], res); } Product(tmp[i & 1], tmp[i & 1], tmp[(i + 1) & 1]); i++; n = n >> 1; } } int main() { #ifdef _DEBUG freopen("d:\\in.txt", "r", stdin); #endif int n, m; memset(State, 0, sizeof(State)); for (int i = 0; i < 16; i++) { InitState(i, i, 0); } int finstates[16][16]; int res[16][16]; memset(Start, 0, sizeof(Start)); Start[0][0] = 1; while (scanf("%d %d", &n, &m) != EOF) { if (n == 0 || m == 0) { break; } IMod = m; QProduct(State, finstates, n); Product(Start, finstates, res); int ans = 0; for (int i = 0; i < 16; i++) { ans += res[i][0]; ans %= IMod; } printf("%d\n", ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。