【题解】ARC141D Non-divisible Set
给定 \(N\) 个数的集合,对于每个数 \(A_i\) 求出是否存在一个大小为 \(M\) 的包含 \(A_i\) 的子集是好的。一个集合是好的当且仅当不存在两个数 \(a,b\in S,a\neq b,a|b\),\(M \le N\le 2M\)。
这道题的关键点在于 \(M \le N \le 2M\) 的条件,这一步几乎占这题的 \(80\%\)。
构造,我们考虑对于 \(1 \sim 2M\) 中选出 \(M\) 个数,我们将每个数写成 \((x,y)\) 表示 \(A_i = x\times 2^y\),那么然后将数塞进桶 \(x\) 中,那么我们发现每个桶中只能选一个且恰好选一个,因为桶的个数就是奇数个数为 \(M\)。
接下来就很套路了,如果两个桶 \(a = kb\),那么 \(b\) 桶中选的数一定大于 \(a\) 桶选的数。那么我们可以贪心求出每个桶中能取得最大值/最小值。时间复杂度 \(\mathcal{O}(N\ln N)\)。
#define N 600006
int n, m, a[N], g[N], w[N], v[N], f[N];
vector<int>c[N];
void ret(){
while(n--)puts("No");
exit(0);
}
int main() {
read(n, m), m <<= 1;
rp(i, n){
int x; read(x), a[i] = x;
int y = __builtin_ctz(x);
c[x >> y].pb(y);
}
rp(i, m)if((i & 1) && c[i].empty())ret();
memset(w, ~0, sizeof(w));
memset(g, ~0, sizeof(g));
pr(i, m)if(i & 1){
for(int j = i + i; j <= m; j += i)cmx(w[i], g[j]);
if(w[i] >= c[i].back())ret();
g[i] = *upper_bound(c[i].begin(), c[i].end(), w[i]);
}
memset(g, ~0, sizeof(g));
memset(f, 0x3f, sizeof(f));
rp(i, m)if(i & 1){
if(f[i] <= c[i].front())ret();
g[i] = *--lower_bound(c[i].begin(), c[i].end(), f[i]);
for(int j = i + i; j <= m; j += i)cmn(f[j], g[i]);
}
rp(i, n){
int y = __builtin_ctz(a[i]);
int x = a[i] >> y;
if(y > w[x] && y < f[x])puts("Yes");
else puts("No");
}
return 0;
}