CF R 632 div2 1333F Kate and imperfection

赛后看了半天题 才把题目看懂 英语水平极差。

意思:定义一个集合S的权值为max{gcd(a,b)};且\(a\neq b\)

这个集合可以从1~n中选出一些数字 求出当集合大小为k时的最小价值。

无法二分 考虑构造。

考虑一种简单的情况 1~n的中gcd(a,b)最大为多少 可以发现我们只需要枚举i 看一下i/i的最小质因子的最大值即可。

所以是从质因子分解的层面考虑比较简单。

可以发现 当两个数字质因子集合有包含关系的时候 加入小的那个数到集合S之中一定不会比大的数加入集合S结果更差。(显然。

所以由上面的引理 可以直接构造一个集合大小为P的S集合 其中P为1~n的质数个数 且S集合为所有1~n的质数集合。

考虑接下来加入哪个数字更优 尽可能让gcd小 所以需要加入的数字为4 此时和其他数字比大小的是含有4的倍数的数字和其他的单个质因子。

不难发现此时6中含有的3是最小的。

可以发现此时考虑加入一个数字的时候 对答案的最大贡献 可以由引理得出 在加入i时 将i质因子分解 然后凡是i的质因数分解的子集此时一定已经加入了。

那么最大的贡献 就是子集最大的 即i/i的最小质因子。

那么我们得到了每个数的贡献排一下序即可。

但是 我在思考的时候 并没有从每个数字的贡献的角度入手而是一直在考虑加入哪个数字然后比大小。

一个方法:正难则反 这里加入数字比大小的时候每次都要考虑更新一些点的值 不妨反过来想加入一个点的时候的值是否有规律。

值得一提的是 所谓规律也是能找到的 譬如加入了i 那么凡是含有i的倍数的数字都要将值更新一下。

然后顺着这个思路 可以暴力更新 这样复杂度是nln的但是每次需要找最大值里面写一个线段树就可以达到nlog^2.

但是 根据我们的引理 就可以很简单的推出 每个数字都会被一个数字更新成最大值 可以发现这个最大值可以被找到 即i/最小质因子。

const int MAXN=500010;
int n,top;
int v[MAXN],p[MAXN],w[MAXN];
inline void prepare()
{
	w[1]=1;
	rep(2,n,i)
	{
		if(!v[i])p[++top]=v[i]=i,w[i]=1;
		rep(1,top,j)
		{
			if(n/i<p[j])break;
			int ww=i*p[j];
			v[ww]=p[j];
			w[ww]=i;
			if(p[j]==v[i])break;
		}
	}
}
int main()
{
	freopen("1.in","r",stdin);
	get(n);prepare();
	sort(w+1,w+1+n);
	rep(2,n,i)printf("%d ",w[i]);
	return 0;
}
posted @ 2020-04-10 16:36  chdy  阅读(107)  评论(0编辑  收藏  举报