AtCoder Beginner Contest 204 F Hanjo 2
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相关推荐
- 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 ...
- AtCoder Beginner Contest 170 F. Pond Skater
AtCoder Beginner Contest 170 F. Pond Skater 题目链接 第一次碰到会写的 F,真的哭辽/(ㄒoㄒ)/~~,BFS+剪枝 题目有几个坑点: 1.初始化,我们直接 ...
- AtCoder Beginner Contest 167 F.Bracket Sequencing
AtCoder Beginner Contest 167 F.Bracket Sequencing 题目链接 判断括号匹配的字符串问题~ 首先给出的所有字符串的左右括号数是要匹配的,这个很好判断,用一 ...
- AtCoder Beginner Contest 187 F.Close Group Editorial
AtCoder Beginner Contest 187 F.Close Group Editorial 题目链接 状压DP~ 如果对边暴力的话复杂度约为 21502^{150}2150,显然不可取, ...
- AtCoder Beginner Contest 194 F - Digits Paradise in Hexadecimal 数位dp
传送门 文章目录 题意: 思路: 题意: 给一个161616进制的串NNN,让你求1−N1-N1−N中有多少个数有kkk个不同的数且没有前导零. 思路: NNN很大,有2e52e52e5了,那么就比较 ...
- AtCoder Beginner Contest 192 F - Potion 背包dp
传送门 题意: 给你nnn个数,让后让你选出来kkk个AAA,把他们求和,之后再递增kkk直到正好达到xxx,求最小的递增次数. 思路: 转化一下题意就是求∑A=x(modlen)\sum A=x(\ ...
- 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 ...
- AtCoder Beginner Contest 187 F - Close Group
https://atcoder.jp/contests/abc187/tasks/abc187_f 有点像小米决赛的G题啊,所以就秒了 dp[i]表示i这个状压状态,最少可以是多少连通块组成 先预处理 ...
- AtCoder Beginner Contest 204 A~E 题解
ABC204 A~E [A - Rock-paper-scissors](https://atcoder.jp/contests/abc204/tasks/abc204_a) 题目大意 输入格式 输出 ...
最新文章
- [CSAcademy]A-Game
- HTC Link是仅适用于日本的6DOF VR头显
- Hibernate CRUD操作
- 性能翻倍 IBM借DS3500拓中低端存储市场
- JSP知识点笔记-常用技术方法
- 为什么使用ES6生成器
- 笨办法学C 练习6:变量类型
- 前端:分享一些实用的JS代码片段
- C#灰度图转伪彩色图
- 框架 go_GoFrame v1.13.1 发布,Go 应用开发框架
- matlab中图例的字怎么改,matlab中legend函数在添加图例时的使用方法
- 桌面魔术可以用透明桌子揭密
- 五个在线,推进企业数字化转型升级
- android9三星功能,三星开启安卓9.0测试:One UI Beta计划
- MTK手机平台及相关
- repaire mysql_sql错误:……is marked as crashed and should be repaire
- 【数论】快速分解质因数的技巧 筛法求素数(快速筛)
- decimals数据格式化
- jq 修改元素css伪类样式
- 读取文件云服务器bcc,云服务器bcc 使用