hihoCode #1151 : 骨牌覆盖问题·二

#1151 : 骨牌覆盖问题·二

Time Limit:10000ms

Case Time Limit:1000ms

Memory Limit:256MB

描述

上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?
所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?
首先我们可以肯定,奇数长度一定是没有办法覆盖的;对于偶数长度,比如2,4,我们有下面几种覆盖方式:

提示:3xN骨牌覆盖

输入

第1行:1个整数N。表示棋盘长度。1≤N≤100,000,000

输出

第1行:1个整数,表示覆盖方案数 MOD 12357

Sample Input
62247088
Sample Output
4037

解题:造转移方程

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long LL;
 4 const LL mod = 12357;
 5 struct Matrix{
 6     int m[8][8];
 7     Matrix(){
 8         init();
 9     }
10     void init(){
11         memset(m,0,sizeof m);
12     }
13     Matrix operator*(const Matrix &rhs){
14         Matrix ret;
15         for(int k = 0; k < 8; ++k)
16             for(int i = 0; i < 8; ++i)
17                 for(int j = 0; j < 8; ++j)
18                     ret.m[i][j] = (ret.m[i][j] + m[i][k]*rhs.m[k][j])%mod;
19         return ret;
20     }
21     void print(){
22         for(int i = 0; i < 8; ++i){
23             for(int j = 0; j < 8; ++j)
24                 printf("%d ",m[i][j]);
25             cout<<endl;
26         }
27     }
28 };
29 Matrix a,b;
30 void quickPow(LL index){
31     while(index){
32         if(index&1) a = a*b;
33         index >>= 1;
34         b = b*b;
35     }
36 }
37 bool tab[10][10];
38 void dfs(int cur,int st){
39     if(cur >= 3){
40         int ss = 0;
41         for(int i = 2; i >= 0; --i){
42             ss <<= 1;
43             ss |= tab[i][1];
44         }
45         b.m[st][ss]++;
46         return;
47     }
48     if(!tab[cur][0]){
49         if(!tab[cur][1]){
50             tab[cur][0] = tab[cur][1] = true;
51             dfs(cur+1,st);
52             tab[cur][0] = tab[cur][1] = false;
53         }
54         if(cur + 1 < 3){
55             if(!tab[cur+1][0]){
56                 tab[cur+1][0] = tab[cur][0] = true;
57                 dfs(cur+2,st);
58                 tab[cur+1][0] = tab[cur][0] = false;
59             }
60         }
61     }else dfs(cur + 1,st);
62 }
63 void init(int st){
64     memset(tab,false,sizeof tab);
65     for(int i = 0,xst = st; i < 3; ++i,xst >>= 1)
66         tab[i][0] = xst&1;
67     dfs(0,st);
68 }
69 int main(){
70     int n;
71     while(~scanf("%d",&n)){
72         b.init();
73         a.init();
74         for(int i = 0; i <= 7; ++i) init(i);
75         a.m[0][0] = 1;
76         quickPow(n);
77         printf("%d\n",a.m[0][0]);
78     }
79     return 0;
80 }

时间: 2024-10-12 16:09:39

hihoCode #1151 : 骨牌覆盖问题·二的相关文章

hihoCoder #1151 : 骨牌覆盖问题&#183;二 (矩阵快速幂,DP)

题意:给一个3*n的矩阵,要求用1*2的骨牌来填满,有多少种方案? 思路: 官网题解用的仍然是矩阵快速幂的方式.复杂度O(logn*83). 这样做需要构造一个23*23的矩阵,这个矩阵自乘n-1次,再来乘以初始矩阵init{0,0,0,0,0,0,0,1}后,变成矩阵ans{x,x,x,x,x,x,x,y},y就是答案了,而x不必管. 主要在这个矩阵的构造,假设棋盘是放竖直的(即n*3),那么考虑在第i行进行填放,需要考虑到第i-1行的所有可能的状态(注意i-2行必须是已经填满了,否则第i行无

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

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

题目1 : 骨牌覆盖问题&#183;二 (矩阵快速幂+分析状态的表示+题目的提示分析很好很经典)

题目1 : 骨牌覆盖问题·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题? 所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢? 首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: [week42_1.PNG] 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,00

[hihoCoder] 题目1 : 骨牌覆盖问题&#183;二

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 12

hiho42 : 骨牌覆盖问题&#183;二

描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 12357 样例输入 62247088 样例输出 4037 提示:3xN骨牌

骨牌覆盖问题&#183;二

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 12357 样例输入 62

c实现:骨牌覆盖问题&#183;二

#include <stdio.h> long MOD = 12357; long N; long a[5]; void solve() { int i = 0; a[0] = 0; a[1] = 2; a[2] = 3; for (i = 3; i <= N; i++) { if (i & 1) { a[i%5] = (2*a[(i-1+5)%5] + a[(i-2+5)%5]) % MOD; } else { a[i%5] = (3*a[(i-2+5)%5] + a[(i-3

斐波那契数列 改1 3*N 骨牌覆盖 改1 hiho一下 第四十二周 递归不行 矩阵加速

题目1 : 骨牌覆盖问题·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数

骨牌覆盖问题

骨牌覆盖问题: 用1*2骨牌完美覆盖n*m棋盘,求方案数 一.2*m 如果骨牌横着放,只能两个横着的骨牌摞在一起 如果竖着放,恰好占一列 所以dp[i]=dp[i-1]+dp[i-2] 即斐波那契数列 二.3*m 可以想到一个递推式:f[n]=a2*f[n-2]+a4*f[n-4]+a6*f[n-6]+……+an*f[0] ai(i是偶数)是未知的系数 即覆盖3*i棋盘且无法按某一列将3*i棋盘分成左右两部分的方案数 当i=2时,有3种方案 当i>=4(i为偶数)时,只有2种 因为考虑最左上角的