题解:P17124 [ICPC 2025 Shanghai R] Not a subset sum
这是一道签到题。
我才不告诉你我最开始使用字典树加线段树合并吃了七发罚时。
思路
考虑暴力枚举字符串
int mid = len >> 1;
int* merge = tmp[dep];
for(int i = 0;i < mid;i ++){
merge[i] = dat[i] + dat[i + mid];
}
这样就可以快速查询答案了,递归函数需要 dfs(int dep,int len,const int* dat),dep 表示深度,len 表示当前区间长度,dat 表示需要处理的数据的指针,我们可以静态存储指针,即先对于每个深度创建数组,每次合并时再调用,递归函数代码:
int tmp[N][1 << (N - 1)];
void dfs(int dep,int len,const int* dat){
if(len == 1){
ans ^= dat[0];
return;
}
int mid = len >> 1;
dfs(dep + 1,mid,dat);
dfs(dep + 1,mid,dat + mid);
int* merge = tmp[dep];
for(int i = 0;i < mid;i ++){
merge[i] = dat[i] + dat[i + mid];
}
dfs(dep + 1,mid,merge);
}
然后就可以 AC 本题了。
Code
#include<bits/stdc++.h>
#define N 16
using namespace std;
int n,dat[1 << N],tmp[N][1 << (N - 1)],ans;
void dfs(int dep,int len,const int* dat){
if(len == 1){
ans ^= dat[0];
return;
}
int mid = len >> 1;
dfs(dep + 1,mid,dat);
dfs(dep + 1,mid,dat + mid);
int* merge = tmp[dep];
for(int i = 0;i < mid;i ++){
merge[i] = dat[i] + dat[i + mid];
}
dfs(dep + 1,mid,merge);
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 0;i < (1 << n);i ++){
cin >> dat[i];
}
dfs(0,1 << n,dat);
cout << ans;
return 0;
}