CF1198F GCD Groups 2

(n) 个数分为两组,使每组的 (gcd=1)。输出分组方案或无解信息。

(2 leq n leq 10^5)(1 leq a_i leq 10^9)


这是Div1F¿我人傻了。

一看到这题完全不会怎么办啊,那就直接随机好了。

先考虑一种贪心思路,加入一个数 (a) 的时候,加入到一个 (gcd) 不是 (a) 的因子的集合,这样子 (gcd) 一定变小了,变得很优。

然而这肯定过不去,所以多随机几遍 (a) 加入的顺序,就能得到解了。

思考一下这样做的正确性,我们注意到 (a) 的质因子最多只有 (9) 个,那么什么时候我们这样子做会错误,就是其中一个集合存在一个公共质因子,而 (10^9) 以内的质数大约有 (5 imes 10^7) 个,所以这样的概率是非常低的,于是就做完了。

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
const int N = 1e5;
const int inf = 1e8;
using namespace std;
int n,a[N + 5],g[3],c[N + 5],id[N + 5];
bool solve()
{
    c[id[1]] = 1;
    g[1] = a[id[1]];
    c[id[2]] = 2;
    g[2] = a[id[2]];
    for (int i = 3;i <= n;i++)
    {
        if (a[id[i]] % g[1] == 0)
        {
            c[id[i]] = 2;
            g[2] = __gcd(g[2],a[id[i]]);
        }
        else
        {
            c[id[i]] = 1;
            g[1] = __gcd(g[1],a[id[i]]);
        }
    }
    return g[1] == 1 && g[2] == 1;
}
int main()
{
    srand(19260817);
    scanf("%d",&n);
    for (int i = 1;i <= n;i++)
        scanf("%d",&a[i]),id[i] = i;
    int fl = 0,T = inf / n / 20;
    T = min(T,2000);
    while (T--)
    {
        g[1] = g[2] = 0;
        random_shuffle(id + 1,id + n + 1);
        fl |= solve();
        if (fl)
        {
            cout<<"YES"<<endl;
            for (int i = 1;i <= n;i++)
                printf("%d ",c[i]);
            return 0;
        }
    }
    cout<<"NO"<<endl;
    return 0;
}
原文地址:https://www.cnblogs.com/sdlang/p/14571433.html