[题解]CF1475G Strange Beauty

题目大意:有 \(n\) 个数,从中挑选一个最大的子集,使得集合中任意两个不同的数 \(x,y\) , 有 \(x|y\)\(y|x\)

我们发现,集合中必然存在一个数 \(x\) ,使得集合中其他数都是 \(x\) 的因数

所以我们只需统计每个数的因数在原数组里的出现次数即可

这里 $a_i \leq 2*10^5 $,可以预处理出每个数的因数

代码:

#include<bits/stdc++.h>
#define rep(i,a,b) for (register int i=(a);i<=(b);i++)
#define drep(i,a,b) for (register int i=(a);i>=(b);i--)
typedef long long ll;
using namespace std;
inline ll read()
{
	ll sum=0,f=0;char c=getchar();
	while (!isdigit(c)) f|=(c=='-'),c=getchar();
	while (isdigit(c)) sum=(sum<<1)+(sum<<3)+(c^48),c=getchar();
	return f?-sum:sum;
}

const int N=200010;
int n,a[N],f[N],cnt[N];
vector<int>fac[N];

inline void init(int size)
{
	rep(i,1,size)
	{
		int x=i<<1;
		while (x<=size) fac[x].push_back(i),x+=i;
	}
}

inline void solve()
{
	memset(cnt,0,sizeof(cnt)),memset(f,0,sizeof(f));
	int mx=0;
	n=read();rep(i,1,n) a[i]=read(),cnt[a[i]]++,mx=max(mx,a[i]);
	int ans=n;
	rep(i,1,mx) if (cnt[i])
	{
		f[i]=cnt[i];
		rep(j,0,(int)fac[i].size()-1)
		{
			if (cnt[fac[i][j]]) f[i]=max(f[i],f[fac[i][j]]+cnt[i]);
		}
		ans=min(ans,n-f[i]);
	}
	cout<<ans<<endl;
}

int main()
{
	init(N-10);
	drep(T,read(),1) solve();
}
posted @ 2021-01-26 20:48  ZSH_ZSH  阅读(68)  评论(0编辑  收藏  举报