AtCoder Beginner Contest 204 F Hanjo 2

H宽,W长的二维平面上,用1 * 1或者2 * 1的地砖来铺,要求铺满,求出方案数。
数据范围H <= 6, W <= 1e12

看到W的范围就可以想到是一个矩阵快速幂优化的dp转移,问题的关键是如何写出dp的方程以及矩阵的构造。

这里题解的巧妙在于状态的定义,因为不好处理1 * 2的地砖横着摆的情况,因为这会跨两行,我开始以为会有2^12,也就是枚举两行的状态。不过这里状态的定义是当前行的二进制状态压缩,并且要保证前一行是已经塞满的情况。所以在构造状态转移矩阵的时候,也就是从当前的状态dp[i][S]dp[i][S]dp[i][S]转移到状态dp[i+1][T]dp[i+1][T]dp[i+1][T]的时候,是要搜索找到当前的状态,也就是S,在加入一些1 * 1和1 * 2的地砖之后变为全1的状态,这时候所对应的T就是dp[i+1][T]dp[i + 1][T]dp[i+1][T]。

而转移矩阵tran[S][T]tran[S][T]tran[S][T]则是从dp[i][S]dp[i][S]dp[i][S]到dp[i+1][T]dp[i + 1][T]dp[i+1][T]转移的方案数。构造出转移矩阵之后用快速幂来把M降到log级别。

dfs那块在看了别人的题解之后照着写的,莫名其妙的就过了。感觉这里比较巧妙,三个递归分别是对应1 * 1,1 * 2横着放和1 * 2竖着放的情况,并且是永远放在当前状态的最上面的空缺,这样是为了避免方案数的重复统计,不过我还没有完全消化完,先放在这里。

const int N = 6, mod = 998244353, M = (1 << 6) + 10;
long long tran[M][M], ans[M][M], temp[M][M];
int n;
long long m;void dfs(int from, int now, int to)
{if (now == (1 << n) - 1)tran[from][to] ++;else{for (int i = 0; i < n; i ++){if(now & (1 << i))continue;dfs(from, now | (1 << i), to);if (i < n - 1 && !(now & (1 << i + 1)))dfs(from, now | (1 << i) | (1 << (i + 1)), to);dfs(from, now | (1 << i), to | (1 << i));break;}}
}int main()
{//freopen("in.txt", "r", stdin);ios::sync_with_stdio(false);cin.tie(0);int T = 1;//cin >> T;while (T --){cin >> n >> m;for (int i = 0; i < (1 << n); i ++){dfs(i, i, 0);ans[i][i] = 1;}while (m){if (m & 1){memset (temp, 0, sizeof (temp));for (int i = 0; i < (1 << n); i ++)for (int j = 0; j < (1 << n); j ++)for (int p = 0; p < (1 << n); p ++){temp[i][j] += ans[i][p] * tran[p][j];temp[i][j] %= mod;}for (int i = 0; i < (1 << n); i ++)for (int j = 0; j < (1 << n); j ++)ans[i][j] = temp[i][j];}memset (temp, 0, sizeof (temp));for (int i = 0; i < (1 << n); i ++)for (int j = 0; j < (1 << n); j ++)for (int p = 0; p < (1 << n); p ++){temp[i][j] += tran[i][p] * tran[p][j];temp[i][j] %= mod;}for (int i = 0; i < (1 << n); i ++)for (int j = 0; j < (1 << n); j ++)tran[i][j] = temp[i][j];m >>= 1;}cout << ans[0][0];}return 0;
}

AtCoder Beginner Contest 204 F Hanjo 2相关推荐

  1. AtCoder Beginner Contest 215 F - Dist Max 2

    AtCoder Beginner Contest 215 F - Dist Max 2 平面上有一系列的点(xi,yi)(x_i,y_i)(xi​,yi​),定义两点(xi,yi),(xj,yj)(x ...

  2. AtCoder Beginner Contest 170 F. Pond Skater

    AtCoder Beginner Contest 170 F. Pond Skater 题目链接 第一次碰到会写的 F,真的哭辽/(ㄒoㄒ)/~~,BFS+剪枝 题目有几个坑点: 1.初始化,我们直接 ...

  3. AtCoder Beginner Contest 167 F.Bracket Sequencing

    AtCoder Beginner Contest 167 F.Bracket Sequencing 题目链接 判断括号匹配的字符串问题~ 首先给出的所有字符串的左右括号数是要匹配的,这个很好判断,用一 ...

  4. AtCoder Beginner Contest 187 F.Close Group Editorial

    AtCoder Beginner Contest 187 F.Close Group Editorial 题目链接 状压DP~ 如果对边暴力的话复杂度约为 21502^{150}2150,显然不可取, ...

  5. AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal 数位dp

    传送门 文章目录 题意: 思路: 题意: 给一个161616进制的串NNN,让你求1−N1-N1−N中有多少个数有kkk个不同的数且没有前导零. 思路: NNN很大,有2e52e52e5了,那么就比较 ...

  6. AtCoder Beginner Contest 192 F - Potion 背包dp

    传送门 题意: 给你nnn个数,让后让你选出来kkk个AAA,把他们求和,之后再递增kkk直到正好达到xxx,求最小的递增次数. 思路: 转化一下题意就是求∑A=x(modlen)\sum A=x(\ ...

  7. Caddi Programming Contest 2021(AtCoder Beginner Contest 193) F.Zebraness

    题目链接 Problem Statement We have a grid with N horizontal rows and N vertical columns. Let (i,j) denot ...

  8. AtCoder Beginner Contest 187 F - Close Group

    https://atcoder.jp/contests/abc187/tasks/abc187_f 有点像小米决赛的G题啊,所以就秒了 dp[i]表示i这个状压状态,最少可以是多少连通块组成 先预处理 ...

  9. AtCoder Beginner Contest 204 A~E 题解

    ABC204 A~E [A - Rock-paper-scissors](https://atcoder.jp/contests/abc204/tasks/abc204_a) 题目大意 输入格式 输出 ...

最新文章

  1. [CSAcademy]A-Game
  2. HTC Link是仅适用于日本的6DOF VR头显
  3. Hibernate CRUD操作
  4. 性能翻倍 IBM借DS3500拓中低端存储市场
  5. JSP知识点笔记-常用技术方法
  6. 为什么使用ES6生成器
  7. 笨办法学C 练习6:变量类型
  8. 前端:分享一些实用的JS代码片段
  9. C#灰度图转伪彩色图
  10. 框架 go_GoFrame v1.13.1 发布,Go 应用开发框架
  11. matlab中图例的字怎么改,matlab中legend函数在添加图例时的使用方法
  12. 桌面魔术可以用透明桌子揭密
  13. 五个在线,推进企业数字化转型升级
  14. android9三星功能,三星开启安卓9.0测试:One UI Beta计划
  15. MTK手机平台及相关
  16. repaire mysql_sql错误:……is marked as crashed and should be repaire
  17. 【数论】快速分解质因数的技巧 筛法求素数(快速筛)
  18. decimals数据格式化
  19. jq 修改元素css伪类样式
  20. 读取文件云服务器bcc,云服务器bcc 使用

热门文章

  1. 编写Qt Designer自定义控件(一)——如何创建并使用Qt自定义控件
  2. 《Effective C++》item25:考虑写出一个不抛异常的swap函数
  3. opencv如何截取子图像
  4. 浮点数在计算机中是如何表示的
  5. 一个能描述erp系统的小故事。
  6. 浅入深出Vue:发布项目
  7. 非刚性人脸跟踪 —— 实用工具
  8. Java 读书笔记 (十一) Number Math 类
  9. Python之路【第七篇】:初识Socket
  10. HDU-3280 Equal Sum Partitions