思路: 令
l
e
n
len
len =2~n内的质数个数+1,最多可以从
n
n
n中选取
l
e
n
len
len个数使得这些数组成的集合的 imperfection值为1。如果集合的大小
k
≤
l
e
n
k\le len
k≤len,那么总能选取
k
k
k个数使得他们之间两两互质,集合的imperfection值为1。 考虑剩下的合数,依次从中选取
1
,
2
,
3...
n
−
l
e
n
1,2,3...n-len
1,2,3...n−len个数加入到之前的
l
e
n
len
len个数组成的集合,且要求集合大小相同的情况下,集合的imperfection值最小。可以发现随着新加入的数的个数不断增多,集合的imperfection值是非递减的。 对于一个合数
x
x
x,若其存在最小的因子
i
i
i,使得
i
∗
j
=
x
i*j=x
i∗j=x,那么加入该合数对集合imperfection值的最大贡献为
j
j
j。(如果集合中出现
j
j
j,那么该集合的imperfection值为
g
c
d
(
j
,
x
)
=
j
gcd(j,x)=j
gcd(j,x)=j)。 综上,2~n内的质数对答案的贡献为1,求出合数对答案的最大贡献,结合“集合的imperfection值是非递减的”这一性质,将得到的
n
−
1
n-1
n−1个值升序排序即可得到答案。 可以在埃氏筛的过程中统计质数和合数对答案的贡献。
ac代码:
#include<bits/stdc++.h>
using namespace std;typedeflonglong ll;const ll mod =998244353;constint maxn =5e5+10;int n;
vector<int> ans;
bool vis[maxn];intmain(){//freopen("/Users/zhangkanqi/Desktop/11.txt","r",stdin);scanf("%d",&n);for(int i =2; i <= n; i++){if(vis[i])continue;
ans.push_back(1);for(int j = i; j <= n/i; j++){if(vis[i*j])continue;
ans.push_back(j);
vis[i*j]= true;}}sort(ans.begin(), ans.end());for(int i =0; i < ans.size(); i++)printf("%d%c", ans[i], i==ans.size()-1?'\n':' ');return0;}