POJ-3734(DP + 矩阵求幂)
2015-03-05 19:22
183 查看
题目:http://poj.org/problem?id=3734
刚开始看到题目N<10^9吓蒙了都,看了discuss才明白,还是对DP理解的太浅呢。。。
分析:我们更多的关心红色和绿色的情况,限制条件是两者个数都是偶数,但子问题却可能出现两者一奇一偶、一偶一奇、两奇的情况,假设已经给n个块染色,且出现这4种情况的场面分别有{a, b, c, d}个,给第n+1个块染色之后可能构成的场面和数量分别为{m, n, p, q},我们来看两者是不是有一定的关系:
1、如果给第n+1个块染红色,则两偶 -> 一奇一偶;一奇一偶 -> 两偶;一偶一奇 -> 两奇;两奇 -> 一偶一奇。
2、如果给第n+1个块染绿色,则两偶 -> 一偶一奇;一奇一偶 -> 两奇;一偶一奇 -> 两偶;两奇 -> 一奇一偶。
3、如果给第n+1个块染黄色,则两偶 -> 两偶;一奇一偶 -> 一奇一偶;一偶一奇 -> 一偶一奇;两奇 -> 两奇。
4、如果给第n+1个块染蓝色,则两偶 -> 两偶;一奇一偶 -> 一奇一偶;一偶一奇 -> 一偶一奇;两奇 -> 两奇。
所以状态n+1的数量可以从状态n的数量中推出来,具体而言,{m, n, p, q}和{a, b, c, d}之间的关系就是:
m = b + c + a + a = 2a + b + c
n = a + d + b + b = a + 2b + d
p = d + a + c + c = a + 2c + d
q = c + b + d + d = b + c + 2d
有点fibonacci的感觉我们有,f[n+1] = f
* m,其中m是递推矩阵, m = [[2, 1, 1, 0], [1, 2, 0, 1], [1, 0, 2, 1], [0, 1, 1, 2]],初始条件f[1] = [2, 1, 1, 0],即
1、第一格染黄色或蓝色 => 两偶(都是0),有2种情况
2、第一格染红色 => 一奇一偶(红1绿0),有1种情况
3、第一格染绿色 => 一偶一奇(红0绿1),有1种情况
4、第一格不可能让红和绿都是奇数
从而f
= f[1] * m ^ (n-1),用矩阵快速幂可以达到O(logn)复杂度。
刚开始看到题目N<10^9吓蒙了都,看了discuss才明白,还是对DP理解的太浅呢。。。
分析:我们更多的关心红色和绿色的情况,限制条件是两者个数都是偶数,但子问题却可能出现两者一奇一偶、一偶一奇、两奇的情况,假设已经给n个块染色,且出现这4种情况的场面分别有{a, b, c, d}个,给第n+1个块染色之后可能构成的场面和数量分别为{m, n, p, q},我们来看两者是不是有一定的关系:
1、如果给第n+1个块染红色,则两偶 -> 一奇一偶;一奇一偶 -> 两偶;一偶一奇 -> 两奇;两奇 -> 一偶一奇。
2、如果给第n+1个块染绿色,则两偶 -> 一偶一奇;一奇一偶 -> 两奇;一偶一奇 -> 两偶;两奇 -> 一奇一偶。
3、如果给第n+1个块染黄色,则两偶 -> 两偶;一奇一偶 -> 一奇一偶;一偶一奇 -> 一偶一奇;两奇 -> 两奇。
4、如果给第n+1个块染蓝色,则两偶 -> 两偶;一奇一偶 -> 一奇一偶;一偶一奇 -> 一偶一奇;两奇 -> 两奇。
所以状态n+1的数量可以从状态n的数量中推出来,具体而言,{m, n, p, q}和{a, b, c, d}之间的关系就是:
m = b + c + a + a = 2a + b + c
n = a + d + b + b = a + 2b + d
p = d + a + c + c = a + 2c + d
q = c + b + d + d = b + c + 2d
有点fibonacci的感觉我们有,f[n+1] = f
* m,其中m是递推矩阵, m = [[2, 1, 1, 0], [1, 2, 0, 1], [1, 0, 2, 1], [0, 1, 1, 2]],初始条件f[1] = [2, 1, 1, 0],即
1、第一格染黄色或蓝色 => 两偶(都是0),有2种情况
2、第一格染红色 => 一奇一偶(红1绿0),有1种情况
3、第一格染绿色 => 一偶一奇(红0绿1),有1种情况
4、第一格不可能让红和绿都是奇数
从而f
= f[1] * m ^ (n-1),用矩阵快速幂可以达到O(logn)复杂度。
#include <cstdio> #include <cstring> #define MOD 10007 const int transfer[][4] = {{2, 1, 1, 0}, {1, 2, 0, 1}, {1, 0, 2, 1}, {0, 1, 1, 2}}; struct Matrix{ int a[4][4]; Matrix operator * (const Matrix& m)const{ Matrix t; int i, j, k, s; for(i = 0; i < 4; ++i){ for(j = 0; j < 4; ++j){ for(s = k = 0; k < 4; ++k) s = (s + a[i][k] * m.a[k][j]) % MOD; t.a[i][j] = s; } } return t; } }; Matrix power(const Matrix& matrix, int n) { if(n == 1) return matrix; Matrix tmp = power(matrix, n >> 1); if(n & 1) return tmp * tmp * matrix; return tmp * tmp; } int main() { int t, n; Matrix matrix, result; memcpy(matrix.a, transfer, sizeof(matrix.a)); for(scanf("%d", &t); t--; ){ scanf("%d", &n); if(n == 1){ puts("2"); continue; } result = power(matrix, n-1); printf("%d\n", (result.a[0][0]*2 + result.a[1][0] + result.a[2][0]) % MOD); } return 0; }
相关文章推荐
- poj 2778 DNA Sequence 【ac自动机 + dp + 矩阵快速幂】
- poj 3734 Blocks(矩阵快速幂)
- poj 3734 <矩阵快速幂模版>
- Poj 3734(矩阵快速幂)
- POJ 3735 Training little cats【矩阵的快速求幂】
- POJ 3734 Blocks 矩阵快速幂
- poj 3734 Blocks(构造矩阵加快速幂)
- 【POJ 3734】【用母函数推公式 或者 矩阵幂】 Blocks【现要给n块砖染红、蓝、绿、黄四种颜色。要求被染成红色和绿色的砖块数量必须为偶数,问染色方案数】
- POJ 3734 Blocks 生成函数及矩阵的解法
- poj3734--blocks(矩阵快速幂)
- poj-3734(矩阵快速幂+推导)
- Poj 3734 Blocks(DP,矩阵乘法优化)
- poj 3734 Blocks (矩阵快速幂优化的动态规划)
- poj 3734 Blocks 矩阵
- [POJ 3734] Blocks (矩阵高速幂、组合数学)
- poj 3734 方块涂色 求红色 绿色方块都为偶数的方案数 (矩阵快速幂)
- POJ 3734 矩阵加速dp
- poj 3734 矩阵快速幂模板清晰版
- poj 3734 Blocks 【矩阵快速幂】
- [POJ 3734] Blocks (矩阵快速幂、组合数学)