[ARC141D] Non-divisible Set
[ARC141D] Non-divisible Set
我们认为 \(n,m\) 同阶。
看起来很像一道小学奥数题,当时我们证明了 \(\{1,2,\dots,2m\}\) 的最大好子集大小为 \(m\)。
考虑当时的做法,我们将 \(x\) 拆分成 \(2^a \times b\),其中 \(b\) 是奇数。
容易发现,这个过程对于所有的 \(b\) 形成了一个类,且一个类内必须选择恰好一个数。
考虑两个不同类的数 \(2^a \times b \mid 2^c \times d\) 的条件:
-
\(a \leq c\)
-
\(b \mid d\)
对于不整除的情况无需考虑,对于 \(b \mid d\),我们一定需要让 \(a > c\)。
于是我们得到了 \(O(n^2)\) 的做法,考虑优化。
我们考虑对于每个 \(b\),求出合法的 \(a\) 范围,这是容易 dp 的。
接下来我们只要判断是否在范围内即可,复杂度 \(O(n \log n)\)。
//Ad astra per aspera
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
vector<int> lst[600010];
int a[600010],b[600010],c[600010],l[600010],r[600010];
vector<int> yinshu[600010],beishu[6000010];
int main(){
int n,m;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=0;
c[i]=a[i];
while(c[i]%2==0){
b[i]++;
c[i]>>=1;
}
lst[c[i]].push_back(b[i]);
}
for(int i=1;i<=2*m-1;i+=2){
for(int j=3*i;j<=2*m;j+=2*i){
yinshu[j].push_back(i);
beishu[i].push_back(j);
}
}
for(int i=1;i<=2*m-1;i+=2){
int minn=0x3f3f3f3f;
for(int j=0;j<yinshu[i].size();j++){
int k=yinshu[i][j];
minn=min(minn,r[k]);
}
vector<int> :: iterator iter=lower_bound(lst[i].begin(),lst[i].end(),minn);
if(iter==lst[i].begin()){
r[i]=-0x3f3f3f3f;
}
else{
iter--;
r[i]=*iter;
}
}
for(int i=2*m-1;i>=1;i-=2){
int maxn=-0x3f3f3f3f;
for(int j=0;j<beishu[i].size();j++){
int k=beishu[i][j];
maxn=max(maxn,l[k]);
}
vector<int> :: iterator iter=upper_bound(lst[i].begin(),lst[i].end(),maxn);
if(iter==lst[i].end()){
l[i]=0x3f3f3f3f;
}
else{
l[i]=*iter;
}
}
for(int i=1;i<=2*m-1;i+=2){
if(l[i]>r[i]){
for(int j=1;j<=n;j++){
printf("No\n");
}
return 0;
}
}
for(int i=1;i<=n;i++){
if(b[i]>=l[c[i]] && b[i]<=r[c[i]]){
printf("Yes\n");
}
else{
printf("No\n");
}
}
return 0;
}

浙公网安备 33010602011771号