1 条题解
-
0
题解说明
问题背景:
这是某类矩阵计数题的实现。给定一个 的 矩阵(字符'0'
或'1'
),需要根据题目要求计算两类答案 和 。参数 和 控制是否输出对应答案。最终结果对 取模。核心思路:
预处理连续 的长度:- 用数组 表示在当前列 上,从位置 开始向下连续
'0'
的长度。 - 遍历时从下往上更新:若 ,则 ,否则 。
列扫描:
- 从右到左枚举每一列 。
- 在每列中,从下到上扫描每一行 。
- 使用三个临时变量:
- :累计的横向贡献
- :累计的纵向贡献
- :计数器,用于控制 的累加
贡献计算:
- 若当前位置 且已有累计贡献 :
- 若当前位置不是
'0'
(),则清空临时变量。 - 否则若下一行 ,说明连续 继续延伸:
输出:
- 每组测试用例结束后,输出 和 。
算法流程:
输入测试用例数 和题目编号 。
对每组测试用例:- 输入 。
- 读入 行矩阵。
- 初始化 数组为 。
- 从右到左枚举列,从下到上更新 并计算贡献。
- 输出结果。
复杂度分析:
- 外层循环 列,内层循环 行,总复杂度 。
- 时可行。
实现细节与注意点:
- 数组初始化为 ,表示没有连续 。
- 从下往上更新 ,保证连续 的长度正确。
- 和 的更新逻辑要区分“断开”和“延续”两种情况。
- 最终答案取模 。
总结:
该代码通过逐列扫描和动态维护连续 的长度,利用临时变量累计贡献,最终在 时间内完成 和 的计算。整体思路是“列枚举 连续 统计```cpp #include "bits/stdc++.h" using namespace std; const int MOD = 998244353; char s[1001][1002]; // 存储输入的字符矩阵 int d[1002]; // 记录当前列中每个位置的连续0长度 int main() { // 去掉文件重定向,保留cin加速配置(优化标准输入效率) ios::sync_with_stdio(false); cin.tie(nullptr); int t, id, n, m, c, f, cnt, i, j; long long nowc, nowf, ansc, ansf; cin >> t >> id; // 标准输入:测试用例数t和题目编号id while (t--) { // 处理每组测试用例 memset(d, -1, sizeof(d)); // 初始化d数组为-1(表示无连续0) cin >> n >> m >> c >> f; // 标准输入:矩阵大小n*m,是否计算ansc和ansf的标志 ansc = ansf = 0; // 初始化当前测试用例的结果 // 标准输入:读入n行字符矩阵(每行从s[i][1]开始存储) for (i = 1; i <= n; i++){ string t; cin>>t; for(int j =1 ;j <= t.size();j++)s[i][j] = t[j-1]; } // 从右到左遍历每一列,计算连续0的贡献 for (j = m; j >= 1; j--) { nowc = nowf = cnt = 0; // 临时变量:当前列的累计贡献 // 从下到上遍历当前列的每一行 for (i = n; i >= 1; i--) { // 更新d[i]:当前位置是'0'则连续长度+1,否则重置为-1 d[i] = (s[i][j] == '0') ? d[i] + 1 : -1; // 若当前有连续0且有累计贡献,累加结果 if (d[i] > 0 && nowc) { ansc += nowc * d[i]; ansf += nowf * d[i]; } // 重置逻辑:当前位置不是连续0,清空临时变量 if (d[i] == -1) { nowc = nowf = cnt = 0; } // 累加逻辑:当前位置的下一行有连续0,更新临时贡献 else if (d[i + 1] != -1) { nowc += d[i + 1]; nowf += cnt++ * d[i + 1]; } } } // 标准输出:根据c和f的标志输出结果(取模MOD) printf("%lld %lld\n", (c ? ansc % MOD : 0), (f ? ansf % MOD : 0)); } return 0; }
- 用数组 表示在当前列 上,从位置 开始向下连续
- 1
信息
- ID
- 3166
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者