http://hihocoder.com/contest/hiho42/problem/1

给定一个n,问我们3*n的矩阵有多少种覆盖的方法

第41周做的骨牌覆盖是2*n的,状态转移方程是dp[i] = dp[i-1] + dp[i-2],递推数列可以用矩阵快速幂来加速计算

我们可以用状态dp来做这一题,如果某个格子上被铺了骨牌,就标记为1,否则为0

那么每一列一共有8个状态。

两种状态的表示法

第一种:

dp[i][s] 表示填满第i行后,第i+1行的状态为s,

那么s的转移情况如下,

0->1,4,7

1->0,6

2->5

3->4

4->0,3

5->2

6->1

7->0

那么就可以构造出转换的矩阵

 int mat[][] = {
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , }
};

初始时,只有状态0存在,状态1,2,3,4,5,6,7都不存在

所以初始的向量为 A = [1,0,0,0,0,0,0,0,0]

转换n次后为,  A*mat^n

转化n次后,获得的是第i+1行的不同状态的个数,我们要的是第i+1行状态为0的个数,即A[0]

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = << ;
const int MOD = ;
/* */
int mat[][] = {
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , }
};
int mat2[][] = {
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
};
struct Matrix
{
int mat[][];
Matrix()
{
memset(mat, , sizeof(mat));
}
};
Matrix operator*(const Matrix &lhs, const Matrix &rhs)
{
Matrix ret;//零矩阵
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
{
for (int k = ; k < ; ++k)
{
ret.mat[i][j] = (ret.mat[i][j] + lhs.mat[i][k] * rhs.mat[k][j]) % MOD;
}
}
} return ret;
}
Matrix operator^(Matrix a, int n)
{
Matrix ret;//单位矩阵
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
ret.mat[i][j] = mat2[i][j];
}
while (n)
{
if (n & )
{
ret = ret * a;
}
n >>= ;
a = a * a;
}
return ret;
} int main()
{
int n;
while (scanf("%d", &n) != EOF)
{ Matrix a;
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
a.mat[i][j] = mat[i][j];
}
a = a^n;
cout << a.mat[][] << endl; }
return ;
}

第二种转换方法为:

dp[i][s]表示填满第i-1行时,第i行的状态为s

同样的,可以得到转化的矩阵, 其实,两种转化的方法就是转化矩阵的不同

 #include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <math.h>
using namespace std;
#pragma warning(disable:4996)
typedef long long LL;
const int INF = <<;
const int MOD = ;
/* */
int mat[][] = {
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , }
};
int mat2[][] = {
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
{ , , , , , , , },
};
struct Matrix
{
int mat[][];
Matrix()
{
memset(mat, , sizeof(mat));
}
};
Matrix operator*(const Matrix &lhs, const Matrix &rhs)
{
Matrix ret;//零矩阵
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
{
for (int k = ; k < ; ++k)
{
ret.mat[i][j] = (ret.mat[i][j] + lhs.mat[i][k] * rhs.mat[k][j]) % MOD;
}
}
} return ret;
}
Matrix operator^(Matrix a, int n)
{
Matrix ret;//单位矩阵
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
ret.mat[i][j] = mat2[i][j];
}
while (n)
{
if (n & )
{
ret = ret * a;
}
n >>= ;
a = a * a;
}
return ret;
} int main()
{
int n;
while (scanf("%d", &n) != EOF)
{
n += ;
Matrix a;
for (int i = ; i < ; ++i)
{
for (int j = ; j < ; ++j)
a.mat[i][j] = mat[i][j];
}
a = a^n;
cout << a.mat[][] << endl; }
return ;
}

hihocoder第42周 3*N骨牌覆盖(状态dp+矩阵快速幂)的更多相关文章

  1. hihocoder第42周 k*N骨牌覆盖(状态dp+矩阵快速幂)

    上周的3*N的骨牌,因为状态只有8中,所以我们可以手算出状态转移的矩阵 但是这周是k*N,状态矩阵不好手算,都是我们改成用程序自动生成一个状态转移的矩阵就行了,然后用这个矩阵进行快速幂即可 枚举枚举上 ...

  2. 棋盘覆盖 状压DP+矩阵快速幂

    题意:有一个m 行n 列的矩形方格棋盘,1 < = m< = 5,1=< n< =10^9,用1*2 的骨牌(可横放或竖放)完全覆盖,骨牌不能重叠,有多少种不同的覆盖的方法.你 ...

  3. hihocoder第41周 骨牌覆盖(矩阵快速幂)

    由于棋盘只有两行,所以如果第i列的骨牌竖着放,那么就转移为第1列到第i-1列骨牌有多少种摆法 如果第一行第i列骨牌横着放,那么第二行第i列也要横着放,那么就转移为了第1列到第i-2列骨牌有多少种方法 ...

  4. hihoCoder 1143 : 骨牌覆盖问题·一(递推,矩阵快速幂)

    [题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形 ...

  5. hihoCoder #1143 : 骨牌覆盖问题·一(矩阵乘法)

    1143 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然 ...

  6. hihoCoder #1151 : 骨牌覆盖问题·二 (矩阵快速幂,DP)

    题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案? 思路: 官网题解用的仍然是矩阵快速幂的方式.复杂度O(logn*83). 这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次, ...

  7. [HIHO1143]骨牌覆盖问题·一(矩阵快速幂,递推)

    题目链接:http://hihocoder.com/problemset/problem/1143 这个递推还是很经典的,结果是斐波那契数列.f(i) = f(i-1) + f(i-2).数据范围太大 ...

  8. hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)

    题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001) 思路: 由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一 ...

  9. hihoCoder#1743:K-偏差排列(矩阵快速幂+状压dp)

    题意 如果一个 \(1\to N\) 的排列 \(P=[P_1, P_2, ... P_N]\) 中的任意元素 \(P_i\) 都满足 \(|P_i-i| ≤ K\) ,我们就称 \(P\) 是 \( ...

随机推荐

  1. 14.6.1 Creating InnoDB Tables 创建InnoDB 表:

    14.6.1 Creating InnoDB Tables 创建InnoDB 表: 创建一个InnoDB 表,使用CREATE TABLE 语句,你不需要指定 ENGINE=InnoDB子句 如果In ...

  2. MPICH3环境配置

    最新版的mpich简化了运行方式,不再提供mpd开头的命令,只需要一个mpiexec即可启动mpi运行环境,方便了mpi编程.源代码下载地址:http://www.mpich.org/download ...

  3. Swift 可展开可收缩的表视图

    主要学习与运行效果 在本节的内容中,我们将通过一个具体实例的实现过程,详细讲解在表视图当中,如何创建一个可展开可收缩的表视图.为了让读者有着更为直观的印象,我们将通过模仿QQ好友列表来实现这个效果. ...

  4. shell 调试

    感觉编写shell在查找错误的过程中,很让你崩溃,还好shell也提供了一些调试的方式: 语法检查      -n选项做语法检查,而不执行脚本      sh -n script_name.sh 启动 ...

  5. codeforces 577

    codeforces 577A 题目链接:http://codeforces.com/problemset/problem/577/A 题目大意:给出一个n*n的表格,每个表格对应的值为横坐标*纵坐标 ...

  6. heapq

    heapq-Guest-ChinaUnix博客 假设你需要维护一个列表,这个列表不断有新的元素加入,你需要在任何时候很方便的得到列表中的最大(小)值,因此要求列表始终处于排序完毕状态,怎么办呢 最简单 ...

  7. [置顶] 如何在Python IDLE中调试Python代码?

    好久没有用Python了,居然忘记了怎么在Python IDLE中调试Python代码.百度了一下,然后还是写下来吧,以免以后又忘记了. 1. Set break point in the sourc ...

  8. Terracotta收购Ehcache (转)

    随着Terracotta对Ehcache的收购成行,业界两大知名的开源Java缓存产品走到了一起.以提供JVM级“POJO集群”而闻名于世的Terracotta可以将运行在单个JVM上的多线程应用移植 ...

  9. ipv6加英文的中括号访问

    加英文的中括号就可以,如[2001:4998:c:e33::1004],我发现这是yahoo首页.但并不是所有IPv6网站都可以通过IPv6地址访问,跟IPv4一样,网站服务器端可以只绑定域名,不接受 ...

  10. PAT-B 1015. 德才论(同PAT 1062. Talent and Virtue)

    1. 在排序的过程中,注意边界的处理(小于.小于等于) 2. 对于B-level,这题是比較麻烦一些了. 源代码: #include <cstdio> #include <vecto ...