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 + 矩阵快速幂)的更多相关文章

  1. [BZOJ4000][TJOI2015]棋盘(状压DP+矩阵快速幂)

    题意极其有毒,注意给的行列都是从0开始的. 状压DP,f[i][S]表示第i行状态为S的方案数,枚举上一行的状态转移.$O(n2^{2m})$ 使用矩阵加速,先构造矩阵a[S1][S2]表示上一行为S ...

  2. BZOJ 4000: [TJOI2015]棋盘( 状压dp + 矩阵快速幂 )

    状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) ------------------------------------------------------- ...

  3. HDU 5434 Peace small elephant 状压dp+矩阵快速幂

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5434 Peace small elephant  Accepts: 38  Submissions: ...

  4. 【BZOJ】2004: [Hnoi2010]Bus 公交线路 状压DP+矩阵快速幂

    [题意]n个点等距排列在长度为n-1的直线上,初始点1~k都有一辆公车,每辆公车都需要一些停靠点,每个点至多只能被一辆公车停靠,且每辆公车相邻两个停靠点的距离至多为p,所有公车最后会停在n-k+1~n ...

  5. BZOJ4000 TJOI2015棋盘(状压dp+矩阵快速幂)

    显然每一行棋子的某种放法是否合法只与上一行有关,状压起来即可.然后n稍微有点大,矩阵快速幂即可. #include<iostream> #include<cstdio> #in ...

  6. 【XSY2524】唯一神 状压DP 矩阵快速幂 FFT

    题目大意 给你一个网格,每个格子有概率是\(1\)或是\(0\).告诉你每个点是\(0\)的概率,求\(1\)的连通块个数\(\bmod d=0\)的概率. 最开始所有格子的概率相等.有\(q\)次修 ...

  7. 2018.09.28 hdu5434 Peace small elephant(状压dp+矩阵快速幂)

    传送门 看到n的范围的时候吓了一跳,然后发现可以矩阵快速幂优化. 我们用类似于状压dp的方法构造(1(1(1<<m)∗(1m)*(1m)∗(1<<m)m)m)大小的矩阵. 然后 ...

  8. BZOJ 2004 公交线路(状压DP+矩阵快速幂)

    注意到每个路线相邻车站的距离不超过K,也就是说我们可以对连续K个车站的状态进行状压. 然后状压DP一下,用矩阵快速幂加速运算即可. #include <stdio.h> #include ...

  9. 瓷砖铺放 (状压DP+矩阵快速幂)

    由于方块最多涉及3行,于是考虑将每两行状压起来,dfs搜索每种状态之间的转移. 这样一共有2^12种状态,显然进行矩阵快速幂优化时会超时,便考虑减少状态. 进行两遍bfs,分别为初始状态可以到达的状态 ...

随机推荐

  1. LOJ2540 PKUWC2018 随机算法 状压DP

    传送门 两种$DP$: ①$f_{i,j}$表示前$i$次选择,最大独立集为$j$时达到最大独立集的方案总数,转移:$a.f_{i,j}+=f_{i+1,j+2^k}$(保证$k$加入后符合条件):$ ...

  2. sqlserver 隔离级别 - 转

    SQL-92标准中定义了四个隔离级别,这四个隔离级别在以前版本的SQL Server中即受到支持: READ UNCOMMITTED READ UNCOMMITTED是限制性最弱的隔离级别,因为该级别 ...

  3. 数据库日志——mysql与Oracle的日志

    一.MySQL 在数据同步中用的比较多的是MySQL的binlog 1.bin-log简介 它记录了所有的DDL和DML(除了数据查询语句,select与show不记录)语句,以事件形式记录,还包含语 ...

  4. Luogu P1477 [NOI2008]假面舞会

    一道非常神奇的图论题解法无比新奇清新 我们首先把图分成三种情况: 有环的,此时答案一定是环长的因数(否则不能满足题意) 存在入度大于1的DAG图的 一棵树/一条链 很容易发现,最后一种情况想怎么取就怎 ...

  5. 【UFUN开发板评测】小巧而不失精致,简单而不失内涵——uFun开发板开箱爆照

    关于uFun学习板--"满满的爱和正能量" uFun是由@张进东 张工组织发起的一个开源的学习板,设计初衷是为了帮助学生更好的理解电子知识和开发技巧,同时又能对学生毕业找工作有很明 ...

  6. 编写一个供浏览器端使用的NPM包

    此文已由作者吴维伟授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 在编写程序时,总会有一些代码是我们不愿意一遍又一遍重复地去写的,比如一些UI或交互相似组件,或是一些相似的流 ...

  7. 七年一冠、IG牛13的背后是什么!

    最近忙着看S8世界总决赛,博客荒废了近一个月,后续步入正轨.   2018年11月3日.S8世界总决赛.中国终于夺得了S系列赛的总冠军. “IG牛逼”也开始刷爆社交圈,对于在S3入坑的我来说,也弥补上 ...

  8. React.js 入门与实战课程思维导图

    原文发表于我的技术博客 我在慕课网的「React.js 入门与实战之开发适配PC端及移动端新闻头条平台」课程已经上线了,在这里分享了课程中的思维导图,供大家参考. 原文发表于我的技术博客 此导图为课程 ...

  9. Gitlab备份和恢复操作记录

    前面已经介绍了Gitlab环境部署记录,这里简单说下Gitlab的备份和恢复操作记录: 1)Gitlab的备份目录路径设置 [root@code-server ~]# vim /etc/gitlab/ ...

  10. 'config.h' file not found 解决过程

    最近将ReactNative业务集成进现有APP项目中,出现了几个具有代表性的问题,下面记录一下 问题1. [!] CocoaPods could not find compatible versio ...