hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)

题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001)

思路:

  由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一个初始矩阵R,求得ans矩阵,然后答案就在ans中了。ans=R*Mn

  M的大小应该是2k*2k,所以当k稍微大一些就不合适存储这个矩阵了,而且里面大部分都是0,很浪费。由于k<8,所以M的大小为128*128是可以接受的。复杂度是O(23*k*logn),大概是千万级别的。

 1 #include <bits/stdc++.h>
 2 #define pii pair<int,int>
 3 #define INF 0x3f3f3f3f
 4 #define LL long long
 5 using namespace std;
 6 const int N=21000;
 7 const int mod=12357;
 8 int k, n;
 9 int M[130][130], grid[130][130], tot[130][130], cur[130][130];
10
11 void DFS(int x,int y,int col)   //构造矩阵M。
12 {
13     if(col==k)
14     {
15         M[y][x]=1;              //表示y可以转移到x
16         return ;
17     }
18     DFS(x<<1, (y<<1)+1, col+1);                      //不放
19     DFS((x<<1)+1, y<<1, col+1);                      //放竖
20     if(col+2<=k)    DFS((x<<2)+3, (y<<2)+3, col+2);  //放横
21 }
22
23 void mul(int A[][130],int B[][130])
24 {
25     for(int i=0; i<(1<<k); i++)
26     {
27         for(int j=0; j<(1<<k); j++)
28         {
29             int tmp=0;
30             for(int q=0; q<(1<<k); q++)
31             {
32                 tmp+=A[i][q]*B[q][j];
33                 tmp%=mod;
34             }
35             grid[i][j]=tmp;
36         }
37     }
38     memcpy(A, grid, sizeof(grid));
39 }
40
41
42 int cal(int t)  //注意t=n-1
43 {
44     memset(M, 0, sizeof(M));
45     memset(tot, 0, sizeof(tot) );
46     memset(cur, 0, sizeof(cur) );
47     DFS( 0, 0, 0);   //求矩阵。
48     memcpy(cur, M, sizeof(M));
49     while(t)
50     {
51         if(t&1) mul(M, cur);    //该位为1
52         mul(cur, cur);  //矩阵自乘
53         t>>=1;
54     }
55     return M[(1<<k)-1][(1<<k)-1];   //矩阵很特殊,只需要这一项。
56 }
57
58 int main()
59 {
60     //freopen("input.txt", "r", stdin);
61     while(~scanf("%d%d", &k, &n))    printf("%d\n", cal(n-1));
62     return 0;
63 }

AC代码

时间: 2024-10-25 22:38:00

hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)的相关文章

hihoCoder #1162 : 骨牌覆盖问题&#183;三

#1162 : 骨牌覆盖问题·三 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法.这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数. 提示:KxN骨牌覆盖 输入 第1行:2个整数N.表示棋盘宽度为k,长度为N.2≤K≤7,1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 1235

bnu 34985 Elegant String(矩阵快速幂+dp推导公式)

Elegant String Time Limit: 1000ms Memory Limit: 65536KB 64-bit integer IO format: %lld      Java class name: Main Prev Submit Status Statistics Discuss Next Type: None None Graph Theory      2-SAT     Articulation/Bridge/Biconnected Component      Cy

VOJ 1067 Warcraft III 守望者的烦恼 (矩阵快速幂+dp)

题目链接 显然可知 dp[n] = dp[n-k] + dp[n-k+1] + ... +dp[n-1]; 然后要用矩阵来优化后面的状态转移. 也就是矩阵 0 1 0 0    a     b 0 0 1 0 * b =  c 0 0 0 1    c     d 1 1 1 1    d    a+b+c+d 然后跑快速幂 #include <iostream> #include <cstdio> #include <algorithm> #include <c

hihoCoder#1743:K-偏差排列(矩阵快速幂+状压dp)

题意: 如果一个 \(1\to N\) 的排列 \(P=[P_1, P_2, ... P_N]\) 中的任意元素 \(P_i\) 都满足 \(|P_i-i| ≤ K\) ,我们就称 \(P\) 是 \(K\)-偏差排列. 给定 \(N\) 和 \(K\) ,请你计算一共有少个不同的排列是 \(K\)-偏差排列. 例如对于 \(N=3\) ,有 \(3\) 个 \(1\)-偏差排列:\([1, 2, 3], [1, 3, 2], [2, 1, 3]\). 由于答案可能非常大,你只需要输出答案模 \

COJ 1208 矩阵快速幂DP

题目大意: f(i) 是一个斐波那契数列 , 求sum(f(i)^k)的总和 由于n极大,所以考虑矩阵快速幂加速 我们要求解最后的sum[n] 首先我们需要思考 sum[n] = sum[n-1] + f(i+1)^k 那么很显然sum[n-1]是矩阵中的一个元素块 那么f(i+1)^k怎么利用f(i) , f(i-1)来求 f(i+1)^k = (f(i) + f(i-1)) ^ k 假如k = 1 , 可以看出f(i+1) = f(i-1) + f(i) (1,1) k = 2 , 可以看出

Codeforces 576D Flights for Regular Customers 矩阵快速幂+DP

题意: 给一个\(n\)点\(m\)边的连通图 每个边有一个权值\(d\) 当且仅当当前走过的步数\(\ge d\)时 才可以走这条边 问从节点\(1\)到节点\(n\)的最短路 好神的一道题 直接写做法喽 首先我们对边按\(d_i\)由小到大排序 设\(f_i\)表示加上\(1\sim i-1\)的所有边走\(d_i\)次后各点间的联通情况 \(G\)表示只连\(1\sim i-1\)的边的邻接矩阵 这些我们可以用一个\(01\)邻接矩阵来存储 则有 \(f_i=f_{i-1}*G^{d_i-

P1357 花园 (矩阵快速幂+ DP)

题意:一个只含字母C和P的环形串 求长度为n且每m个连续字符不含有超过k个C的方案数 m <= 5  n <= 1e15 题解:用一个m位二进制表示状态 转移很好想 但是这个题是用矩阵快速幂加速dp的 因为每一位的转移都是一样的 用一个矩阵表示状态i能否转移到状态j 然后跑一遍 初试模板题 #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9 + 7; ll n,

hihocoder 1151 骨牌覆盖问题 二 (矩阵快速幂)

思路见hihocoder,用的kuangbin的矩阵快速幂,一次AC,6的一笔. #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <string> #include <stack> #include <cmath> #include <queue> #include <set>

hihoCoder 1143 : 骨牌覆盖问题&#183;一(递推,矩阵快速幂)

[题目链接]:click here~~ 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题: 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢? 举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 M