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

题目链接:

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+矩阵快速幂。

  做了好几天,终于敲出来了!。。

  详细题解,明天补充,先睡为敬>

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 using namespace std;
 5
 6 const int maxn = 155;
 7 const int mod = 1000000007;
 8
 9 typedef long long LL;
10
11 struct Matrix {
12     int n, m;
13     int val[maxn][maxn];
14     Matrix(int n,int m) :n(n),m(m) {}
15     Matrix() {}
16     void init(int n, int m) { this->n = n; this->m = m; }
17     friend Matrix operator * (const Matrix& mat1, const Matrix& mat2) {
18         Matrix ret(mat1.n, mat2.m);
19         for (int i = 0; i < ret.n; i++) {
20             for (int j = 0; j < ret.m; j++) {
21                 ret.val[i][j] = 0;
22                 for (int k = 0; k < mat1.m; k++) {
23                     ret.val[i][j] += (LL)mat1.val[i][k] * mat2.val[k][j]%mod;
24                     ret.val[i][j] %= mod;
25                 }
26             }
27         }
28         return ret;
29     }
30 };
31
32 void power(Matrix& mat, int n, Matrix& ans) {
33     while (n > 0) {
34         if (n % 2) ans = mat*ans;
35         mat = mat*mat;
36         n /= 2;
37     }
38 }
39
40 int _n, m;
41
42 bool isOk(int s1, int s2) {
43     for (int i = 0; i<m; i++) {
44         if ((s1&(1 << i)) && !(s2&(1 << i))) {
45             int j;
46             j = i - 1;
47             if (j >= 0) {
48                 if ((s2&(1 << j)) && !(s1&(1 << j))) return false;
49             }
50             j = i + 1;
51             if (j<m) {
52                 if ((s2&(1 << j)) && !(s1&(1 << j))) return false;
53             }
54         }
55     }
56     return true;
57 }
58
59 Matrix mat, ans;
60
61 void init() {
62     mat.init(1 << m, 1 << m);
63     for (int i = 0; i<mat.n; i++) {
64         for (int j = 0; j<mat.m; j++) {
65             if (isOk(i, j)) mat.val[i][j] = 1;
66             else mat.val[i][j] = 0;
67         }
68     }
69
70     ans.init(1 << m, 1);
71     for (int i = 0; i < ans.n; i++) ans.val[i][0] = 1;
72 }
73
74 int main() {
75     while (scanf("%d%d", &_n, &m) == 2 && _n) {
76         init();
77         power(mat, _n - 1, ans);
78         int res = 0;
79         for (int i = 0; i < ans.n; i++) {
80             res += ans.val[i][0];
81             res %= mod;
82         }
83         printf("%d\n", res);
84     }
85     return 0;
86 }

时间: 2024-12-09 14:28:33

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

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

状压dp, 然后转移都是一样的, 矩阵乘法+快速幂就行啦. O(logN*2^(3m)) --------------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define b(x) (1 <&l

POJ 3420 Quad Tiling 状压DP+矩阵快速幂

链接:http://poj.org/problem?id=3420 题意:给一个4*N(1 ≤ N ≤ 1e9)的矩形空间,并且给不限块数的1*2的多米诺骨牌,问是由多少种方式能把这个矩形空间填满. 思路:看到这种问题果断想到状压,虽然是在看矩阵的时候看到的这道题.dp[i][j]表示在第i行状态为j的情况下的填满方式数,j的二进制表示中0表示对应位置上一行的骨牌是竖放,或者对应位置的骨牌是横放,1则表示该行该位置的骨牌是竖放.由于N最大1e9所以O(n)的DP绝对超时,用矩阵快速幂来加速DP递

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

未加矩阵快速幂 50分 1 const dx:array[1..8,1..3] of longint= 2 ((-1,0,0),(-1,0,0),(1,0,0),(0,1,0),(-1,0,0),(-1,1,0),(0,1,0),(-1,0,1)); 3 dy:array[1..8,1..3] of longint= 4 ((0,1,0),(0,-1,0),(0,-1,0),(1,0,0),(0,1,-1),(0,0,-1),(1,0,-1),(0,1,0)); 5 mo=65521; 6 va

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

HDU 5564 Clarke and digits 状压dp+矩阵加速

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在[L,R]范围,并且能整除7的整数的总数. 题解: 考虑最原始的想法: dp[i][j][k]表示长度为i,并且对7取模得到j的以k结尾的数. 则有状态转移方程dp[i+1][(h*10)+l)%7][k]+=dp[i][h][k'](k+k'!=K). 但是i范围是1~10^9,需要矩阵加速. 这里对dp[i][j][k]的[j][k]两个状态进行压缩,得到转移矩阵mat[

HDU 4114 Disney&#39;s FastPass (状压DP)

题意:给定 n 个区域,然后给定两个区域经过的时间,然后你有 k 个景点,然后给定个每个景点的区域和有票没票的等待时间,从哪些区域能够得到票,问你从景点1开始,最后到景点1,而且要经过看完这k个景点. 析:一个状压DP,dp[s1][s2][i] 表示已经访问了 s1 中的景点,拥有 s2 的票,当前在 i 区域,然后两种转移一种是去下一个景点,另一种是去下一个区域拿票.当时输入,写错了,卡了好长时间.... 代码如下: #pragma comment(linker, "/STACK:10240

POJ 2411 &amp;&amp; HDU 1400 Mondriaan&#39;s Dream (状压dp 经典题)

Mondriaan's Dream Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 12341   Accepted: 7204 Description Squares and rectangles fascinated the famous Dutch painter Piet Mondriaan. One night, after producing the drawings in his 'toilet series

HDU 4906 Our happy ending (状压DP)

HDU 4906 Our happy ending 题目链接 题意:给定n个数字,每个数字可以是0-l,要选其中一些数字,然后使得和为k,问方案 思路:状压dp,滚动数组,状态表示第i个数字,能组成的数字状态为s的状态,然后每次一个数字,循环枚举它要选取1 - min(l,k)的多少,然后进行状态转移 代码: #include <cstdio> #include <cstring> typedef long long ll; const int N = (1<<20)

HDU 4856 Tunnels(BFS+状压DP)

HDU 4856 Tunnels 题目链接 题意:给定一些管道,然后管道之间走是不用时间的,陆地上有障碍,陆地上走一步花费时间1,求遍历所有管道需要的最短时间,每个管道只能走一次 思路:先BFS预处理出两两管道的距离,然后状态压缩DP求解,dp[s][i]表示状态s,停在管道i时候的最小花费 代码: #include <cstdio> #include <cstring> #include <queue> #include <algorithm> using