BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
2016-01-25 10:40
246 查看
![](http://images2015.cnblogs.com/blog/723896/201601/723896-20160125103725176-1466652470.png)
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m))
---------------------------------------------------------------------------------------------
#include<cstdio>#include<cstring>#include<algorithm> using namespace std; #define b(x) (1 << (x))typedef unsigned int matrix[100][100];const int maxn = 9; bool OK[b(maxn)];int N, n, U, M, D, p, k;matrix Q, res, mat; void Init() { scanf("%d%d%d%d", &N, &n, &p, &k); U = M = D = 0; for(int i = 0; i < p; i++) { int v; scanf("%d", &v); if(v) U |= b(i); } for(int i = 0; i < p; i++) { int v; scanf("%d", &v); if(v) M |= b(i); } for(int i = 0; i < p; i++) { int v; scanf("%d", &v); if(v) D |= b(i); } M ^= b(k);} bool chk(int x) { for(int i = 0; i < n; i++) if(x & b(i)) { if(i <= k && ((M >> (k - i)) & x)) return 0; if(i > k && ((M << (i - k)) & x)) return 0; } return true;} unsigned int Jud(int x, int y) { for(int i = 0; i < n; i++) { if(b(i) & x) { if(i <= k && ((D >> (k - i)) & y)) return 0U; if(i > k && ((D << (i - k)) & y)) return 0U; } if(b(i) & y) { if(i <= k && ((U >> (k - i)) & x)) return 0U; if(i > k && ((U << (i - k)) & x)) return 0U; } } return 1U;} void Work() { for(int s = b(n); s--; ) OK[s] = chk(s); for(int i = b(n); i--; ) if(OK[i]) for(int j = b(n); j--; ) if(OK[j]) Q[j][i] = Jud(i, j); for(int i = b(n); i--; ) res[i][i] = 1U; for(N--; N; N >>= 1) { if(N & 1) { for(int i = b(n); i--; ) for(int j = b(n); j--; ) { mat[i][j] = res[i][j]; res[i][j] = 0; } for(int k = b(n); k--; ) for(int i = b(n); i--; ) for(int j = b(n); j--; ) res[i][j] += Q[i][k] * mat[k][j]; } for(int i = b(n); i--; ) for(int j = b(n); j--; ) { mat[i][j] = Q[i][j]; Q[i][j] = 0; } for(int k = b(n); k--; ) for(int i = b(n); i--; ) for(int j = b(n); j--; ) Q[i][j] += mat[i][k] * mat[k][j]; } unsigned int ans = 0; for(int i = b(n); i--; ) if(OK[i]) for(int j = b(n); j--; ) if(OK[j]) ans += res[i][j]; printf("%u\n", ans);} int main() { Init(); Work(); return 0;}---------------------------------------------------------------------------------------------
4000: [TJOI2015]棋盘
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 355 Solved: 159
[Submit][Status][Discuss]
Description
![](http://www.lydsy.com/JudgeOnline/upload/201504/222(1).png)
Input
输入数据的第一行为两个整数N,M表示棋盘大小。第二行为两个整数P,K,表示攻击范围模板的大小,以及棋子在模板中的位置。接下来三行,每行P个数,表示攻击范围的模版。每个数字后面一个空格。Output
一个整数,表示可行方案Mod 2 ^32Sample Input
2 23 1
0 1 0
1 1 1
0 1 0
Sample Output
7HINT
1<=N<=10^6,1<=M<=6Source
相关文章推荐
- org.jdom 解析xml
- css怪异模式总结
- [leetcode] 34. Search for a Range
- 很多时候我都很庆幸自己能够成为一个程序员,为什么呢?
- 客制化物料搬运单流程
- DSP/BIOS简介
- leetcode----Evaluate Reverse Polish Notation
- cocoapad 安装
- 时间分发拦截机制
- http和socket之长连接和短连接区别
- fresco如何配合PhotoView使用实现图片缩放
- Python开发基础-day1
- iOS-CoreGraphics(CGAffineTransform.h)
- Python字符编码详解
- nyoj8
- Android开发的那些坑和小技巧
- GDAL2.0编译之添加HDF库编译C#版本
- AjaxFileUpLoad 上传图片
- 对比时间返回时间差
- dom4j 解析xml 文档