2020牛客暑期多校训练营(第四场)H Harder Gcd Problem

给一个数nn,小于nn的公因数大于1的两个数可以组合在一起,求最多有多少组数。

构造:从小于nn的最大素数pp开始,尽量将pp的倍数组合在一起,如果pp的倍数的个数为偶数,则将2×p2\times p留下,直到p=2p=2时将这个数用上。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<cstring>
#include<stack>
#include <cmath>

#define mem(ss) memset(ss,0,sizeof(ss))
#define rep(d, s, t) for(int d=s;d<=t;d++)
#define rev(d, s, t) for(int d=s;d>=t;d--)
#define inf 0x3f3f3f3f
typedef long long ll;
typedef long double ld;
typedef double db;
typedef std::pair<int, int> pii;
typedef std::pair<ll, ll> pll;
const ll mod = 1e9 + 7;
const int N = 2e5 + 10;
#define io_opt ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;

ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

int T, n;
int pri[N], tot=0, mp[N];
inline void sieve() {
    mp[1] = 1;
    for (int i = 2; i <= N; i++) {
        if (!mp[i]) pri[++tot] = i;
        for (int j = 1; j <= tot && i * pri[j] <= N; j++) {
            mp[i * pri[j]] = 1;
            if (i % pri[j] == 0) break;
        }
    }
}
int hashv[N];
int main() {
    sieve();
    cin >> T;
    while (T--) {
        mem(hashv);
        vector<pii> ans;
        cin >> n;
        int k = upper_bound(pri+1,pri+tot+1,n)-pri-1;
        for(int i=k;i>=1;i--){
            int cnt=0,t=(n/pri[i])*pri[i];
            queue<int> q;
            q.push(pri[i]);
            while(t>pri[i]){
                if(!hashv[t]) q.push(t);
                t-=pri[i];
            }
            while(q.size()>=2){
                int f1=q.front();q.pop();
                int f2=q.front();q.pop();
                ans.push_back(pii(f1,f2));
                hashv[f1]=hashv[f2]=1;
            }
        }
        cout << ans.size()<<endl;
        for(pii x:ans){
            cout << x.first <<' '<<x.second << endl;
        }
    }
    return 0;
}
posted @ 2020-07-21 16:31  Mr.doublerun  阅读(18)  评论(0)    收藏  举报