【BZOJ4000】【LOJ2104】【TJOI2015】棋盘 (状压dp + 矩阵快速幂)
Description
有一个\(~n~\)行\(~m~\)列的棋盘,棋盘上可以放很多棋子,每个棋子的攻击范围有\(~3~\)行\(~p~\)列。用一个\(~3 \times p~\)的矩阵给出了棋子攻击范围的模板,棋子被默认在模板中的第一行,第\(~k~\)列,模板中棋子能攻击到的位置标记为\(~1\),不能攻击到的位置是\(~0\) 。输入数据保证模板中的第二行第\(~k~\)列是\(~1\)。在要求棋子互相不能攻击到的前提下,求摆放棋子的方案数。
\(~1 \leq p \leq m,~ 1 \leq k \leq p, ~1 \leq n \leq {10 ^ 6}~, ~1 \leq m \leq 6~\).
Solution
对于这个“要求棋子互相不能攻击到的前提下”的约束条件,先考虑普通\(~dp~\)转移, 记\(~dp_{i,~j}~\)表示第\(~i~\)行状态为\(~j~\)的方案书, 可以发现\(~dp_i~\)的某些状态是从\(~dp_{i - 1}~\)的合法状态转移而来的。但这样的话对于\(~dp_i~\)要枚举\(~dp_{i - 1}~\)和\(~dp_i~\)的合法状态, 时间复杂度\(~O({2^ {2m}}n)~\),显然不行。
发现从\(~dp_i~\)转移到\(~dp_{i + 1}~\)的方式是一样的, 考虑矩阵快速幂加速,枚举任意两个状态并判断其是否可以转移即可, 可以转移当且仅当在两行的任意\(~1~\)的位置放棋子都不会攻击到其他任意一个棋子。
要注意的是这题的下标全是从\(~0~\)开始的。。。
Code
#include<bits/stdc++.h>
#define Set(a, b) memset(a, b, sizeof (a))
#define For(i, j, k) for(int i = j; i <= k; ++i)
using namespace std;
inline int read() {
int x = 0, p = 1; char c = getchar();
for(; !isdigit(c); c = getchar()) if(c == '-') p = -1;
for(; isdigit(c); c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
return x *= p;
}
inline void File() {
#ifndef ONLINE_JUDGE
freopen("bzoj4000.in", "r", stdin);
freopen("bzoj4000.out", "w", stdout);
#endif
}
const int N = (1 << 6) + 5;
typedef unsigned int uint;
struct matrix { uint a[N][N]; } a, b;
int n, m, p, k, atk[3], all, now;
inline matrix operator * (const matrix a, const matrix b) {
matrix c; Set(c.a, 0);
For(i, 0, all) For(k, 0, all) For(j, 0, all)
c.a[i][j] += a.a[i][k] * b.a[k][j];
return c;
}
inline matrix qpow(matrix a, int b) {
matrix res; For(i, 0, all) res.a[i][i] = 1;
for (; b; a = a * a, b >>= 1) if (b & 1) res = res * a;
return res;
}
inline bool check(int st1, int st2) {
For(i, 0, m - 1) if (st1 & (1 << i)) {
if (i > k) now = atk[1] << (i - k); else now = atk[1] >> (k - i);
if ((now & st1) != (1 << i)) return false;
}
For(i, 0, m - 1) if (st2 & (1 << i)) {
if (i > k) now = atk[1] << (i - k); else now = atk[1] >> (k - i);
if ((now & st2) != (1 << i)) return false;
}
For(i, 0, m - 1) if (st1 & (1 << i)) {
if (i > k) now = atk[2] << (i - k); else now = atk[2] >> (k - i);
if (now & st2) return false;
}
For(i, 0, m - 1) if (st2 & (1 << i)) {
if (i > k) now = atk[0] << (i - k); else now = atk[0] >> (k - i);
if (now & st1) return false;
}
return true;
}
int main() {
File();
cin >> n >> m >> p >> k;
For(i, 0, 2) For(j, 0, p - 1) atk[i] |= (read() << j);
all = (1 << m) - 1;
For(s, 0, all) For(t, 0, all) if (check(s, t)) a.a[t][s] = 1;
For(i, 0, all) b.a[i][0] = 1;
b = qpow(a, n - 1) * b;
uint ans = 0;
For(i, 0, all) ans += b.a[i][0];
printf("%u", ans);
return 0;
}
【BZOJ4000】【LOJ2104】【TJOI2015】棋盘 (状压dp + 矩阵快速幂)的更多相关文章
- [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)
题意极其有毒,注意给的行列都是从0开始的. 状压DP,f[i][S]表示第i行状态为S的方案数,枚举上一行的状态转移.$O(n2^{2m})$ 使用矩阵加速,先构造矩阵a[S1][S2]表示上一行为S ...
- BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )
状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...
- HDU 5434 Peace small elephant 状压dp+矩阵快速幂
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant Accepts: 38 Submissions: ...
- 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂
[题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...
- BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)
显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...
- 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT
题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...
- 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)
传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...
- BZOJ 2004 公交线路(状压DP+矩阵快速幂)
注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...
- 瓷砖铺放 (状压DP+矩阵快速幂)
由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移. 这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态. 进行两遍bfs,分别为初始状态可以到达的状态 ...
随机推荐
- BZOJ4911: [Sdoi2017]切树游戏
BZOJ 4911 切树游戏 重构了三次.jpg 每次都把这个问题想简单了.jpg 果然我还是太菜了.jpg 这种题的题解可以一眼秒掉了,FWT+动态DP简直是裸的一批... 那么接下来,考虑如何维护 ...
- 介绍一个axios调试好用的工具:axios-mock-adapter
上一篇文章中写到用promise时应注意的问题,这一篇文章继续介绍一个可以和axios库配合的好工具: axios-mock-adapter.axios-mock-adapter可以用来拦截http请 ...
- es5中for...in 和es6中 for..of遍历
//定义一个数组 var arr=['A','B','C']; //定义一个对象 var obj={name:'张三',age:20} // for..in 遍历数组 得到索引 for(var x i ...
- STM32串口打印输出乱码的解决办法
前言 最近在试用uFUN开发板,下载配套的Demo程序,串口数据输出正常,当使用另一个模板工程,调用串口printf调试功能时,输出的却是乱码,最后发现是外部晶振频率不一样.很多STM32开发板都是使 ...
- [UWP 自定义控件]了解模板化控件(2.1):理解ContentControl
UWP的UI主要由布局容器和内容控件(ContentControl)组成.布局容器是指Grid.StackPanel等继承自Panel,可以拥有多个子元素的类.与此相对,ContentControl则 ...
- http状态码 301、302区别
http状态码301和302详解及区别——辛酸的探索之路 [HTTP]状态码301与302 HTTP返回码中301与302的区别 http状态码301和302详解及区别
- M2阶段测试报告
一.安全漏洞测试报告: http://files.cnblogs.com/hotsbuaa/M2-安全漏洞测试.pdf 二.全面兼容测试: http://files.cnblogs.com/hotsb ...
- 第三周Linux学习报告
Linux内核源代码简介: arch/x86中内容重点关注 init目录重要,内核启动相关的代码基本上都在init目录下.如main.c等.Start_kernel函数相当于普通C程序的main函数. ...
- gitbub感想
Git 是 Linux 的创始人 Linus Torvalds 开发的开源和免费的版本管理系统,利用底层文件系统原理进行版本控制的工具.Git是目前为止最著名运用最好最受欢迎的分布式的配置管理工具. ...
- PAT 1021 个位数统计
https://pintia.cn/problem-sets/994805260223102976/problems/994805300404535296 给定一个k位整数N = d~k-1~*10^ ...