CodeForces 1333F
题意:是在 (S) 中挑选长度是 (2sim n) 的子集合,要求这些子集合中 (S_k{a,b,c,...}) 任意元素 (max(gcd(a,b))) 的值最小。
首先集合是你去选的,那么先去想怎么是的最后选出的子集和中任意两个元素的 (gcd) 的最大值最小,首先考虑质数,我们先考虑把质数放到挑选出的集合中,因为当集合中只有质数时,任意两个质数的 (gcd) 都是 (1) ,最终这个最大值就是 (1) ,那么最多能够放的质数的个数就是小于等于 (n) 的质数个数 (tot), 所以前 (tot) 个都是 (1) .
那么考虑后面的答案:例子:
(S={1,2,3,4,5,6,7,8,9})
现在已经选了 (2,3,5,7) ,(1) 没有影响先不考虑。
那么还剩下 (4,6,8,9) 最终都要放到选择的集合中,因为 (S) 要挑选 长度是 (k(kleq n)) 的子集。
考虑现在放什么:当前已选择的集合是 (2,3,5,7) (ans = 1)
为了使得加入后的值最小,应该先选择 (2) 的倍数即 (4) 这样当 (4) 加入集合中时集合变为:
(2,3,4,5,7) (ans= 2) 不能找到更小的值了。
现在还有 (6,8,9) 考虑加入哪一个:如果加入 (8) 的话,(gcd(4,8)=4)
加入 (6) :(gcd(3,6) = 3)
加入 (9) : (gcd(3,9) = 3)
不可能加入 (8) 那么加入是 (6) 还是 (9) ?
考虑后面的计算其实都是一样的。即先放 (6,9),再放 (8)
那么最终每次的答案是当前合数的最大的因子。
如:(9) 的最大因子是 (3)
(8) 的最大因子是 (4)
(6) 的最大因子是 (3)
最后答案要排个序,这里就是象征着我每次在未选集合中挑选一个数加入已选集合。
先尽量挑选答案小的,最后没有办法了,再加入答案大的。
#include <bits/stdc++.h>
#define SZ(X) ((int)(X).size())
#define ALL(X) (X).begin(), (X).end()
#define rep(I, N) for (int I = 1; I <= (N); ++I)
#define repp(I, N) for (int I = 0; I < (N); ++I)
#define FOR(I, A, B) for (int I = (A); I <= (B); ++I)
#define FORR(I, A, B) for (int I = (A); I >= (B); I--)
#define SORT_UNIQUE(c) (sort(c.begin(), c.end()), c.resize(distance(c.begin(), unique(c.begin(), c.end()))))
#define GET_POS(c, x) (lower_bound(c.begin(), c.end(), x) - c.begin())
#define MP make_pair
#define PB push_back
#define MS0(X) memset((X), 0, sizeof((X)))
#define MS1(X) memset((X), -1, sizeof((X)))
#define LEN(X) strlen(X)
#define F first
#define S second
using namespace std;
const int N = 5e5 + 5;
const double eps = 1e-7;
const int mod = 1e9 + 7;
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
typedef pair<int, int> PII;
typedef vector<int> VI;
typedef vector<LL> VL;
typedef vector<PII> VPII;
typedef pair<LL, LL> PLL;
typedef vector<PLL> VPLL;
LL gcd(LL a, LL b) { return b > 0 ? gcd(b, a % b) : a; }
LL ksm(LL a, LL b)
{
LL ans = 1;
while (b)
{
if (b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
int prime[N], is_prime[N];
int tot = 0;
vector<int> v;
unordered_map<int, int> mp;
void sieve(int n)
{
for (int i = 0; i <= n; i++)
is_prime[i] = 1;
is_prime[0] = is_prime[1] = 0;
for (int i = 2; i <= n; i++)
{
if (is_prime[i])
{
prime[++tot] = i;
for (int j = i + i; j <= n; j += i)
{
is_prime[j] = 0;
}
}
}
}
int main()
{
int n;
cin >> n;
sieve(n);
for (int i = 1; i <= tot; i++)
{
cout << 1 << ' ';
}
for (int i = 2; i <= n; i++)
{
for (int j = i + i; j <= n; j += i)
mp[j] = max(mp[j], i);
}
for (int i = 2; i <= n; i++)
{
if (!is_prime[i]) // 找到合数
{
v.push_back(mp[i]);
}
}
sort(v.begin(), v.end());
for (int i = 0; i < v.size(); i++)
cout << v[i] << ' ';
cout << endl;
return 0;
}