POJ 3734 Blocks DP优化

来源:互联网 发布:西安网络电视在线直播 编辑:程序博客网 时间:2024/05/16 09:55

题目:http://poj.org/problem?id=3734

分析

设 f[i][1] 为第 i 位使红绿色块总数都为偶的方案
f[i][2] …… 红奇绿偶
f[i][3] …… 红偶绿奇
f[i][4] …… 红奇绿奇
则归纳可得,对于相邻的两位 i, j (i < j)

j1=i12+i21+i31+i40
j2=i11+i22+i30+i41
j3=i11+i20+i32+i41
j4=i10+i21+i31+i42
显然可以用矩阵乘法,详见百度
其实是博主也不太会分析
为避免 TLE ,需要使用快速幂

代码片

#include<cstdio>#include<cstring>#include<algorithm>const int M = 10007;using namespace std;int x[4][4] = {{2, 1, 1, 0}, {1, 2, 0, 1}, {1, 0, 2, 1}, {0, 1, 1, 2}};struct Matrix {    int h, w;    int k[4][4];    Matrix() { h = 4, w = 4; memset(k, 0, sizeof(k)); }};Matrix cal(Matrix a, Matrix b) {    Matrix c;    for(int i = 0; i < 4; i++) for(int j = 0; j < 4; j++) for(int l = 0; l < 4; l++)         c.k[i][j] += a.k[i][l] * b.k[l][j], c.k[i][j] %= M;    return c;}Matrix work(Matrix f, int n) {    Matrix x = f;    if(n == 1) return f;    f = work(f, n>>1);    f = cal(f, f);    if(n & 1) f = cal(f, x);    return f;}int main() {    int t, n;    scanf("%d", &t);    while(t--) {        Matrix f;        memcpy(f.k, x, sizeof(x));        scanf("%d", &n);        f = work(f, n);        printf("%d\n", f.k[0][0] % M);    }    return 0;}
0 0
原创粉丝点击