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

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

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

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include 

#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;
}

你可能感兴趣的:(数论)