专栏文章
题解:P11122 [ROIR 2024] 表格游戏 (Day 1)
P11122题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minrodpa
- 此快照首次捕获于
- 2025/12/02 07:15 3 个月前
- 此快照最后确认于
- 2025/12/02 07:15 3 个月前
首先很自然的将剩下的数的和转为删去的数的和。看到 首先想到 枚举第 行删或不删的状态,此时删除每一列的贡献就确定了,我们需要在 个数中选出一些数使得和为一个常数。直接考虑每个数删或不删的复杂度是 的,总复杂度达到了 ,不能通过。
考虑将这 个数分成两个大小为 的部分,两个部分分别可以用 的复杂度计算出 个和。设我们要求的和的常数为 ,我们在第一组和中枚举到了 ,那么我们仅需检验第二组和中是否有 即可。使用
unordered_map 等恰当的实现即可做到单次检验 ,总时间复杂度 ,可以通过。Code:
CPP#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
const int maxn = 15 + 10;
int n, m;
long long k;
int a[maxn][maxn];
long long b[maxn];
unordered_map<long long, int> f;
int main(){
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; j++){
scanf("%d", &a[i][j]);
}
}
scanf("%lld", &k), k = -k;
for (int i = 1; i <= n; i++){
for (int j = 1; j <= m; k += a[i][j++]);
}
for (int sta = 0; sta < 1 << n; sta++){
long long now = k;
for (int i = 1; i <= n; i++){
if (sta >> i - 1 & 1){
for (int j = 1; j <= m; now -= a[i][j++]);
}
}
for (int i = 1; i <= m; i++){
b[i] = 0;
for (int j = 1; j <= n; j++){
!(sta >> j - 1 & 1) && (b[i] += a[j][i]);
}
}
f.clear();
for (int st = 0; st < 1 << (m >> 1); st++){
long long sum = 0;
for (int i = 1; i <= m >> 1; i++){
st >> i - 1 & 1 && (sum += b[i]);
}
f[sum] = st;
}
for (int st = 0; st < 1 << m - (m >> 1); st++){
long long sum = 0;
for (int i = m; i > m >> 1; i--){
st >> m - i & 1 && (sum += b[i]);
}
if (f.count(now - sum)){
printf("YES\n%d\n", __builtin_popcount(sta) + __builtin_popcount(f[now - sum]) + __builtin_popcount(st));
for (int i = 1; i <= n; i++){
sta >> i - 1 & 1 && printf("1 %d\n", i);
}
for (int i = 1; i <= m >> 1; i++){
f[now - sum] >> i - 1 & 1 && printf("2 %d\n", i);
}
for (int i = m; i > m >> 1; i--){
st >> m - i & 1 && printf("2 %d\n", i);
}
return 0;
}
}
}
printf("NO");
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...