CodeForces 1333F

CodeForces 1333F

题意:是在 \(S\) 中挑选长度是 \(2\sim 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(k\leq 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;
}

posted @ 2020-04-09 09:57  strategist_614  阅读(211)  评论(0编辑  收藏  举报