2020牛客多校第四场H-Harder Gcd Problem

https://ac.nowcoder.com/acm/contest/5669/H

题意

从1~N的数选择尽量多的数对,使得每个数对gcd大于1,输出任意一种方案

题解

p*2>n 的 p 必然不能匹配,将它们除去。

倒序枚举所有质因子 p,考虑所有是 p 的倍数、且未被匹配的数,任意将它们进行匹配。

如果个数是奇数就留下 p*2。

最后把剩下的偶数都随意匹配一下。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
struct READ {
    inline char read() {
    #ifdef _WIN32
        return getchar();
    #endif
        static const int IN_LEN = 1 << 18 | 1;
        static char buf[IN_LEN], *s, *t;
        return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
    }
    template <typename _Tp> inline READ & operator >> (_Tp&x) {
        static char c11, boo;
        for(c11 = read(),boo = 0; !isdigit(c11); c11 = read()) {
            if(c11 == -1) return *this;
            boo |= c11 == '-';
        }
        for(x = 0; isdigit(c11); c11 = read()) x = x * 10 + (c11 ^ '0');
        boo && (x = -x);
        return *this;
    }
} in;

const int N = 2e5 + 50;
int vis[N];
int prime[N];
int notprime[N];
int main() {
    int tot = 0;
    int nn = 2e5 + 20;
    for (int i = 2; i <= nn; i++) {
        if (!notprime[i]) prime[++tot] = i;
        for (int j = 1; j <= tot && i * prime[j] <= nn; j++) {
            notprime[i * prime[j]] = 1;
            if (i % prime[j] == 0) break;
        }
    }
    int t; in >> t;
    while (t--) {
        int n; in >> n;
        memset(vis, 0, sizeof(vis));
        vector<int> a, b;
        for (int i = n; i >= 2; i--) {
            if (vis[i]) continue;
            if (notprime[i]) continue;
            vector<int> s;
            s.clear();
            for (int j = 1; j * i <= n; j++) {
                if (!vis[j * i]) s.push_back(j * i);
            }
            if (s.size() == 1) continue;
            if (s.size() & 1) {
                int cnt = 0;
                for (int i = 0; i < s.size(); i++) {
                    if (i == 1) continue;
                    cnt++;
                    if (cnt & 1) a.push_back(s[i]);
                    else b.push_back(s[i]);
                    vis[s[i]] = 1;
                }
            }
            else {
                for (int i = 0; i < s.size(); i++) {
                    if (i & 1) a.push_back(s[i]);
                    else b.push_back(s[i]);
                    vis[s[i]] = 1;
                }
            }
        }
        printf("%d
", a.size());
        for (int i = 0; i < a.size(); i++) {
            printf("%d %d
", a[i], b[i]);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/artoriax/p/13594608.html