
cf1511E - Colorings and Dominoes
快速幂计算: 逆元计算: 预计算幂次数组:预计算了快速幂的结果,用于多次查询。 遍历网格:计算白格子数量,并遍历每个可能的多米诺骨牌位置,计算其贡献。 总贡献计算:将所有贡献加起来,并对结果取模。
发布日期:2021-05-07 22:06:56
浏览次数:17
分类:精选文章
本文共 2705 字,大约阅读时间需要 9 分钟。
在一个n×m的格子图中,每个白格子可以被染成蓝色或红色。多米诺骨牌可以覆盖两个连续的红色格子(水平)或两个连续的蓝色格子(垂直)。我们需要计算所有染色方案下,贡献最多多米诺骨牌的数量的总和,并对998244353取模。
解决方法
计算多米诺骨牌数量:
- 水平方向上的多米诺骨牌数量为n×(m-1)。
- 垂直方向上的多米诺骨牌数量为m×(n-1)。
- 总数为n×(m-1) + m×(n-1)。
计算期望贡献:
- 每个骨牌水平放置的概率为1/4(两个红色)。
- 每个骨牌垂直放置的概率为1/4(两个蓝色)。
- 总期望贡献为1/2。
计算白格子数量w:
- 遍历整个网格,统计白格子的数量。
计算总贡献:
- 总贡献为 [n×(m-1) + m×(n-1)] × 1/2 × 2^w。
取模运算:
- 计算快速幂2^w mod 998244353。
- 最终结果为 [n×(m-1) + m×(n-1)] × 1/2 × (2^w mod 998244353) mod 998244353。
代码实现
#includeusing namespace std;typedef long long ll;const ll mod = 998244353;const int N = 3e5 + 10;ll qpow(ll x, ll n) { ll res = 1; while (n) { if (n & 1) res = res * x % mod; x = x * x % mod; n >>= 1; } return res;}ll inv(ll x) { return qpow(x, mod - 2);}ll po[N];int main() { ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n, m; cin >> n >> m; string mp[n]; for (int i = 0; i < n; ++i) { cin >> mp[i]; } ll white = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (mp[i][j] == '*') continue; white++; } } int len = max(n, m) + 3; ll nwres = 0; for (int i = 2; i <= len; ++i) { if (i % 2 == 0) { nwres = (nwres + inv(qpow(2, i))) % mod; } else { nwres = (nwres - inv(qpow(2, i)) + mod) % mod; } po[i] = nwres; } ll total = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { if (mp[i][j] == '*') continue; ll cnt = 0; for (int k = 0; k < 2; ++k) { if (k == 0 && j + 1 >= m) continue; if (k == 1 && i + 1 >= n) continue; if (mp[i + k][j] == '*') cnt = 0; else cnt++; } if (cnt > 0) { total = (total + po[cnt]) % mod; } } } for (int j = 0; j < m; ++j) { for (int i = 0; i < n; ++i) { if (mp[i][j] == '*') continue; ll cnt = 0; for (int k = 0; k < 2; ++k) { if (k == 0 && i + 1 >= n) continue; if (k == 1 && j + 1 >= m) continue; if (mp[i + k][j] == '*') cnt = 0; else cnt++; } if (cnt > 0) { total = (total + po[cnt]) % mod; } } } ll half = inv(2); ll power = qpow(2, white, mod); total = total * half % mod; total = total * power % mod; cout << total << endl;}
代码解释
qpow
函数用于计算快速幂,用于处理大数的模运算。inv
函数计算模逆元,用于处理分数模运算。通过上述步骤,我们可以高效地解决问题,并得到正确的结果。
发表评论
最新留言
路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月11日 13时36分04秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
递归复习--二叉搜索树
2019-03-05
jvm-02
2019-03-05
spring boot@Value和bean执行顺序问题
2019-03-05
从浏览器输入网址到服务器返回经历的过程
2019-03-05
解决Genymotion无法拖拽的问题
2019-03-05
中国石油大学《计算机文化基础》在线考试(客观题)
2019-03-05
机器学习(numpy/matplotlib/scipy)学习笔记
2019-03-05
HTML CSS JS 特殊字符表
2019-03-05
codeforces The Eternal Immortality 题解
2019-03-05
蓝桥杯 历届试题 幸运数 (堆+DFS)
2019-03-05
微信js-sdk使用简述(分享,扫码功能等)
2019-03-05
selenium 的介绍和爬取 jd数据
2019-03-05
python-selenium优化方案
2019-03-05
服务器 centos 系统漏洞快速修复简易方法
2019-03-05
【分享-一键在线抠图】在线免费去除图片背景
2019-03-05
图片预览自适应固定宽高div
2019-03-05
layui表格checkbox选择全选样式及功能
2019-03-05
mxsrvs支持thinkphp3.2伪静态
2019-03-05