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. token令牌

    本文摘自 WebApi安全性 使用TOKEN+签名验证 首先问大家一个问题,你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或 ...

  2. SPOJ GSS(Can you answer the Queries)系列 7/8

    GSS1 线段树最大子段和裸题,不带修改,注意pushup. 然而并不会猫树之类的东西 #include<bits/stdc++.h> #define MAXN 50001 using n ...

  3. Java8中的HashMap分析

    本篇文章是网上多篇文章的精华的总结,结合自己看源代码的一些感悟,其中线程安全性和性能测试部分并未做实践测试,直接是“拿来”网上的博客的. 哈希表概述 哈希表本质上一个数组,数组中每一个元素称为一个箱子 ...

  4. java 基础01

    标识符:字母,下划线和美元符号,数字组成大小写敏感,无长度限制 关键字: 数据类型

  5. 值类型和引用类型的区别,struct和class的区别

    C#值类型和引用类型 1.简单比较 值类型的变量直接存储数据,而引用类型的变量持有的是数据的引用,数据存储在数据堆中. 值类型(value type):byte,short,int,long,floa ...

  6. 关于树莓派HDMI转VGA线接显示器黑屏

    经过数种折腾,找到了解决方法,在SD卡内有个config.txt文件,在其中找到“#hdmi_safe=1”,把#消除掉,变更后成为 # uncomment if you get no picture ...

  7. Linux ip forward

    Linux 默认带有 ip forward 功能,只不过因为各种原因,默认的配置把该功能关闭了.本文通过 demo 来演示 Linux 的 ip forward 功能,具体场景为:开启 Linux 的 ...

  8. 《坦克世界》1.0+:使用 CPU 优化的图形和物理丰富用户体验

    本文以<坦克世界>为例,介绍 Wargaming 使用 CPU 多核和 CPU 单指令多数据 (SIMD) 功能显著提升游戏沉浸式体验的创新方法.我们以英特尔® 线程构建模块(英特尔® T ...

  9. mysql连接数设置操作(Too many connections)及设置md5值的加密密码

    mysql在使用过程中,发现连接数超了~~~~ [root@linux-node1 ~]# mysql -u glance -h 192.168.1.17 -pEnter password: ERRO ...

  10. bootstrap完善按钮组bug

    .btn.active { border: 1px solid #ff9400 !important; color: #ff9400 !important; } <div class=" ...