hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)
2015-09-03 21:20
267 查看
题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001)
思路:
由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一个初始矩阵R,求得ans矩阵,然后答案就在ans中了。ans=R*Mn。
M的大小应该是2k*2k,所以当k稍微大一些就不合适存储这个矩阵了,而且里面大部分都是0,很浪费。由于k<8,所以M的大小为128*128是可以接受的。复杂度是O(23*k*logn),大概是千万级别的。
AC代码
思路:
由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一个初始矩阵R,求得ans矩阵,然后答案就在ans中了。ans=R*Mn。
M的大小应该是2k*2k,所以当k稍微大一些就不合适存储这个矩阵了,而且里面大部分都是0,很浪费。由于k<8,所以M的大小为128*128是可以接受的。复杂度是O(23*k*logn),大概是千万级别的。
#include <bits/stdc++.h> #define pii pair<int,int> #define INF 0x3f3f3f3f #define LL long long using namespace std; const int N=21000; const int mod=12357; int k, n; int M[130][130], grid[130][130], tot[130][130], cur[130][130]; void DFS(int x,int y,int col) //构造矩阵M。 { if(col==k) { M[y][x]=1; //表示y可以转移到x return ; } DFS(x<<1, (y<<1)+1, col+1); //不放 DFS((x<<1)+1, y<<1, col+1); //放竖 if(col+2<=k) DFS((x<<2)+3, (y<<2)+3, col+2); //放横 } void mul(int A[][130],int B[][130]) { for(int i=0; i<(1<<k); i++) { for(int j=0; j<(1<<k); j++) { int tmp=0; for(int q=0; q<(1<<k); q++) { tmp+=A[i][q]*B[q][j]; tmp%=mod; } grid[i][j]=tmp; } } memcpy(A, grid, sizeof(grid)); } int cal(int t) //注意t=n-1 { memset(M, 0, sizeof(M)); memset(tot, 0, sizeof(tot) ); memset(cur, 0, sizeof(cur) ); DFS( 0, 0, 0); //求矩阵。 memcpy(cur, M, sizeof(M)); while(t) { if(t&1) mul(M, cur); //该位为1 mul(cur, cur); //矩阵自乘 t>>=1; } return M[(1<<k)-1][(1<<k)-1]; //矩阵很特殊,只需要这一项。 } int main() { //freopen("input.txt", "r", stdin); while(~scanf("%d%d", &k, &n)) printf("%d\n", cal(n-1)); return 0; }
AC代码
相关文章推荐
- HTTP 状态码的完整列表
- 关于结构体的操作符重载和定义在内部的函数
- 继承中的构造方法
- Python
- 函数指针数组
- AJAX学习笔记
- newssoj1004逐个击破attack(排序+并查集)
- jQuery基础学习4——jQuery容错性
- 背包问题
- 蓝懿-打飞机图片,内存管理基础 刘国斌老师
- poj 2155 Matrix(二维树状数组)
- C++模板类编写需要注意的一点
- [转]在Ubuntu中安装Python科学计算环境
- [转载]Qt之中文显示(QMessageBox、QLineEdit右键菜单等)
- 蓝汛ChinaCache助力大阅兵全球直播
- 运用Polygon类绘制六边形
- UVALive 7043 International Collegiate Routing Contest 字典树
- 详解SVN提交更新七大准则
- 实现ArcGIS水文分析计算汇流累积量功能
- (*(void(*) ())0)()------这是什么?