专栏文章
题解:CF1955G GCD on a grid
CF1955G题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mioxoeuh
- 此快照首次捕获于
- 2025/12/03 02:50 3 个月前
- 此快照最后确认于
- 2025/12/03 02:50 3 个月前
题目大意
对于 的网格中,每一个格子都有一个对应的 ,求出从 到 路径中所有数的最大公约数所能达到的最大值。
思路简述
好水的绿题。
观察到数据范围 较小,且 。
考虑暴力乱搞。
由于所有路径必定经过 ,所以最后输出的答案必定为 的因数。
故而我们可以先找出 的所有因数,从大到小到暴力枚举答案,每个检验一下是否存在合法方案,若存在,则输出。
如何检验呢。
考虑用 表示第 行 列的位置是否可以到达,则转移方程可以表示为:
这里存约数时使用优先队列或者开个数组排序一下都可以,个人认为优先队列更方便一些,所以我是使用优先队列实现的。
这里要记得每次检验答案是否成立时要清空 数组和队列,而且 memset 容易超时。
结合代码看看挺好懂的,结束撒花撒花。
考虑暴力乱搞。
由于所有路径必定经过 ,所以最后输出的答案必定为 的因数。
故而我们可以先找出 的所有因数,从大到小到暴力枚举答案,每个检验一下是否存在合法方案,若存在,则输出。
如何检验呢。
考虑用 表示第 行 列的位置是否可以到达,则转移方程可以表示为:
这里存约数时使用优先队列或者开个数组排序一下都可以,个人认为优先队列更方便一些,所以我是使用优先队列实现的。
这里要记得每次检验答案是否成立时要清空 数组和队列,而且 memset 容易超时。
结合代码看看挺好懂的,结束撒花撒花。
代码实现
CF提交记录
马蜂良好。
CPP马蜂良好。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 110;
int a[N][N], f[N][N];
priority_queue<int> q;
int n, m;
bool check (int x) { // 检验
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
f[i][j] = 0;
}
}
f[1][1] = 1; // 初始化
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
if (i == 1 && j == 1) continue;
if (a[i][j] % x == 0) {
f[i][j] = f[i - 1][j] | f[i][j - 1]; // 从上方和左边转移
}
}
}
return f[n][m]; // 返回
}
void solve () {
while (!q.empty()) q.pop(); // 清空
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= m; j ++ ) {
cin >> a[i][j];
}
}
for (int i = 1; i <= sqrt(a[1][1]); i ++ ) {
if (a[1][1] % i == 0) {
q.push(i); q.push(a[1][1] / i);
}
} // 处理因数
while (!q.empty()) {
int x = q.top(); q.pop();
if (check(x)) { // 检验
cout << x << "\n";
return;
}
}
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int T; cin >> T;
while (T --) solve();
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...