题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=5434

Peace small elephant

 Accepts: 38
 Submissions: 108
 Time Limit: 10000/5000 MS (Java/Others)
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
小明很喜欢国际象棋,尤其喜欢国际象棋里面的大象(只要无阻挡能够斜着走任意格),但是他觉得国际象棋里的大象太凶残了,于是他想到了小象,
小象就没有大象那么凶残,它的攻击范围是它当前格子直角所斜对的格子。现在小明要在棋盘上放很多个小象,有趣的是,当两个小象所在格子有公共边时,
它们将合体变成合体象,多个小象满足条件也会合体,合体象的攻击范围也是它所覆盖格子区域直角所斜对的格子,现在要求任何一个象的攻击范围上是空的(即不摆放棋子),
小明的棋盘很特殊,有m*nm∗n个格子,求满足条件的摆放的方案数,由于方案数太大,需要对10000000071000000007取模。
下面给出几种形状下的象的攻击范围图,叉号表示攻击范围。
输入描述
输入有多组数据(最多55组),每组数据有两个整数n,mn,m含义如题目描述。
1 \leq m \leq 7,1 \leq n \leq 10000000001≤m≤7,1≤n≤1000000000
输出描述
每组数据对应输出一行包含一个整数,表示满足条件的摆放的方案数。
输入样例
1 1
2 3
输出样例
2
50

题解:

  状压dp+矩阵快速幂。

  由于m很小,我们考虑将每一列m行的状态压缩成一行,这一行对应的状态总数就是2^m种(m=7时,即:0000000~1111111)。

  接下来我们求一个矩阵mat[i][j],代表状态i和状态j是否冲突(比如说0000000和1111111不冲突,而1000000和0100000则冲突)。

如果坐标(i,j),(i+1,j+1)存在小象,那么必须保证(i+1,j),(i,j+1)两个位置至少有一个棋子,按照这个规则,就能提前得到状态转移矩阵mat了。

  然后我们要一列一列的往棋盘上放棋子了(注意这时候棋盘已经状压成1*n了,是线性结构,而不是二维结构),由于我们已经得到转移矩阵mat[1<<m][1<<m]了,初始向量vec[1<<m]为全1(因为第一列所有的(1<<m)种状态都不会发生冲突,所以为全1)。我们的任务就是要求:

  mat^(n-1)*vec (mat^(n-1)表示做n-1次的矩阵乘)

  由于n非常大,所以我们需要用矩阵快速幂来求mat^(n-1);

  总的时间复杂度为 o( (2^m)*(2^m)*(2^m)*(logn) )=o(3e6)

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
using namespace std; const int maxn = ;
const int mod = ; typedef long long LL; struct Matrix {
int n, m;
int val[maxn][maxn];
Matrix(int n,int m) :n(n),m(m) {}
Matrix() {}
void init(int n, int m) { this->n = n; this->m = m; }
//把向量看作是n*1的矩阵,所以不用考虑矩阵*向量的情况了。
friend Matrix operator * (const Matrix& mat1, const Matrix& mat2) {
Matrix ret(mat1.n, mat2.m);
for (int i = ; i < ret.n; i++) {
for (int j = ; j < ret.m; j++) {
ret.val[i][j] = ;
for (int k = ; k < mat1.m; k++) {
ret.val[i][j] += (LL)mat1.val[i][k] * mat2.val[k][j]%mod;
ret.val[i][j] %= mod;
}
}
}
return ret;
}
}; //矩阵快速幂
void power(Matrix& mat, int n, Matrix& ans) {
while (n > ) {
if (n % ) ans = mat*ans;
mat = mat*mat;
n /= ;
}
} int _n, m; //判断状态s1和状态s2是否冲突。
bool isOk(int s1, int s2) {
for (int i = ; i<m; i++) {
if ((s1&( << i)) && !(s2&( << i))) {
int j;
j = i - ;
if (j >= ) {
if ((s2&( << j)) && !(s1&( << j))) return false;
}
j = i + ;
if (j<m) {
if ((s2&( << j)) && !(s1&( << j))) return false;
}
}
}
return true;
} Matrix mat, ans; void init() {
mat.init( << m, << m);
for (int i = ; i<mat.n; i++) {
for (int j = ; j<mat.m; j++) {
if (isOk(i, j)) mat.val[i][j] = ;
else mat.val[i][j] = ;
}
}
ans.init( << m, );
for (int i = ; i < ans.n; i++) ans.val[i][] = ;
} int main() {
while (scanf("%d%d", &_n, &m) == && _n) {
init();
power(mat, _n - , ans);
int res = ;
for (int i = ; i < ans.n; i++) {
res += ans.val[i][];
res %= mod;
}
printf("%d\n", res);
}
return ;
}

HDU 5434 Peace small elephant 状压dp+矩阵快速幂的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  8. BZOJ2004 HNOI2010公交线路(状压dp+矩阵快速幂)

    由数据范围容易想到矩阵快速幂和状压. 显然若要满足一辆公交车的相邻站台差不超过p,则每相邻p个站台中每辆车至少经过一个站台.可以发现这既是必要的,也是充分的. 开始的时候所有车是相邻的.考虑每次把一辆 ...

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

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

随机推荐

  1. 在客户端模拟调用srv和topic

    rostopic pub -r 10 /toipic_name Tab+Tab rosservice call /service_name  Tab+Tab rostopic pub -r 10 /c ...

  2. Oracle入门第五天(上)——数据库对象之视图

    一.概述 1.什么是视图(VIEW) 视图 从表中抽出的逻辑上相关的数据集合(是一张虚表). 2.为什么使用视图 1.控制访问 2.简化查询 3.视图的分类 二.视图管理 1.创建视图 CREATE ...

  3. 20155213 2016-2017-2《Java程序设计》课程总结

    20155213 2016-2017-2<Java程序设计>课程总结 每周作业链接汇总 预备作业1:我所期望的师生关系 预备作业2:C语言的学习的回忆 预备作业3:小议linux 第一周作 ...

  4. 20155307 2017-2018-2 《Java程序设计》第2周学习总结

    20155307 2017-2018-2 <Java程序设计>第2周学习总结 教材学习内容总结 整数:short(2 byte).int(4 byte).long(8 byte) 字节(b ...

  5. 20155334 实验五 Java网络编程及安全

    20155334 实验五 Java网络编程及安全 实验内容 1.掌握Socket程序的编写: 2.掌握密码技术的使用: 3.设计安全传输系统. 实验步骤 实验1: 参考 结对实现中缀表达式转后缀表达式 ...

  6. 考研编程练习----Kruskal

    #include <stdio.h> #include <stdlib.h>   #define MAX 100   /* 定义边(x,y),权为w */ typedef st ...

  7. spring源码-aop动态代理-5.3

    一.动态代理,这是一个很强大的东西哦.研发过程中我们会常用很多业务类,但是存在一个问题.如何在不修改源码逻辑的情况下,加入自己的相关逻辑.比如异常处理,日志记录等! 二.Java动态代理的两种方式JD ...

  8. bzoj4998 星球联盟

    bzoj4998 星球联盟 原题链接 题解 先按照输入顺序建一棵树(森林),然后用一个并查集维护联盟的关系,对于不是树上的边\(a-b\),就把\(a-lca(a,b),b-lca(a,b)\)全部合 ...

  9. bootstrap 4 panels已被card替换

    https://www.zhihu.com/question/34838389?sort=created 解决问题的思路不对,不应该搜不到就各种着急,应该理清思路, 既然 bootstrap4没有了3 ...

  10. Kettle定时执行

    1,Kettle跨平台使用.    例如:在AIX下(AIX是IBM商用UNIX操作系统,此处在LINUX/UNIX同样适用),运行Kettle的相关步骤如下:    1)进入到Kettle部署的路径 ...