持续创作,加速成长!这是我参与「掘金日新计划 · 1 月更文挑战」的第20天,点击查看活动详情
题目链接
题目
Kate has a set of integers .
She thinks that imperfection of a subset is equal to the maximum of over all pairs such that both and are in and .
Kate is a very neat girl and for each she wants to find a subset that has the smallest imperfection among all subsets in of size . There can be more than one subset with the smallest imperfection and the same size, but you don't need to worry about it. Kate wants to find all the subsets herself, but she needs your help to find the smallest possible imperfection for each size kk, will name it .
Please, help Kate to find .
题目大意
给定一个含有 到 中所有正整数的集合 。
定义集合的权值为该集合中任意一对不相等的数字的最大公约数的最大值。我们需要求 个答案,第 个答案表示所有的大小为 的 的子集中,权值最小的子集的权值是多少。
即对于 中所有的 ,构造大小为 的集合 ,最小化 并输出。
思路
如果我们选中的集合里包含数字 ,但是不包含 的因数 ,考虑用 替换 :
- 被选中的集合的大小显然不会改变。
- 被我们选中的集合集合的权值只可能不变或者下降,不可能上升。
所以我们用 替换掉 答案一定不会变差。
当我们把一个数 加入到被我们选中的集合中时,它所有的因数一定已经在这个集合中了,而此时它和被我们选中的集合中的任一元素的最大公约数的最大值就是 的最大的因数。
所以我们只需要预处理出 到 中所有元素的不包括本身的最大因数 ,将其从小到大排序后顺序加入被我们选中的集合里即可。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=500001;
int d[N],n;
priority_queue<int,vector<int>,greater<int>> q;
int main()
{
scanf("%d",&n);
d[1]=1;
for (int i=1;i*2<=n;++i)
{
for (int j=2;i*j<=n;++j)
d[i*j]=i;
}
for (int i=1;i<=n;++i) q.push(d[i]);
q.pop();
while (!q.empty())
{
printf("%d ",q.top());
q.pop();
}
return 0;
}