1. 程式人生 > 實用技巧 >牛客多校第四場自閉

牛客多校第四場自閉

自閉場,不想多說,能做的就2個簽到和H了,難度2.0就是字典樹上字尾自動機,知識儲備限制了我的想象

H-Harder Gcd Problem

先掛個線性篩把範圍內素數都篩一下,然後直接lowerbound找到第一個小於n的素數位置(實際上至少要小於等於n/2,我懶,直接lowerbound到n了),然後從大往小依次處理

對於每一個素數,讓\(j=(n/p[i])*p[i]\)(即找到最後一個j使得jp[i]<=n),然後把j向1列舉,每兩個jp[i]組成一對答案,但對於j為奇數的情況,2*p[i]得先暫時保留

最後再遍歷沒被匹配的數,這時剛剛2*p[i]中帶有2的因子,因此他們也能夠相互匹配,這樣再把它們兩兩匹配

我的處理是先讓1*p[i]處於待匹配狀態,若j為偶數,則2也能被匹配;若j為奇數,則2只能進入待匹配狀態,而不會被匹配


#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define fastio ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
using namespace std;
double pi = acos(-1);
const double eps = 1e-12;
const int maxn = 4e5 + 10;
const int inf = 1e9;
ll mod = 1e9 + 7;
int read()
{
    int x = 0, f = 1;
    char c = getchar();
    while (c < '0' || c>'9') { if (c == '-') f = -1; c = getchar(); }
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + c - '0', c = getchar();
    return f * x;
}
 
int v[maxn], p[maxn], ecnt, vis[maxn], cnt = 0;
 
 
void Euler_sieve(int n)
{
    ecnt = 0;
    for (int i = 2; i <= n; i++) {
        if (v[i] == 0) { v[i] = i; p[++ecnt] = i; }
        for (int j = 1; j <= ecnt; j++)
        {
            if (p[j] > v[i] || p[j] > n / i)break;
            v[i * p[j]] = p[j];
        }
    }
}
 
struct an {
    int a, b;
}ans[maxn];
 
 
int main()
{
    fastio;
    int t;
    cin >> t;
    Euler_sieve(3e5 + 5);
    while(t--)
    {
        memset(vis, 0, sizeof(vis));
        int n;
        cin >> n;
        cnt = 0;
        int P = lower_bound(p + 1, p + 1 + ecnt, n) - p - 1;
        int tmp = -1;
        for (int i = P; i >= 1; i--)
        {
            tmp = p[i];
                for (int j = n / p[i] * p[i]; j > p[i]; j -= p[i])
                {
                    if (!vis[j])
                    {
                        if (tmp == -1)
                            tmp = j;
                        else
                        {
                            ans[++cnt] = { tmp,j };
                            vis[tmp] = vis[j] = 1;
                            tmp = -1;
                        }
                    }
                }
        }
        tmp = -1;
        for (int i = 2; i <= n; i += 2)
        {
            if (!vis[i])
                if (tmp == -1)
                    tmp = i;
                else
                {
                    ans[++cnt] = { tmp,i };
                    vis[tmp] = vis[i] = 1;
                    tmp = -1;
                }
        }
        cout << cnt << endl;
        for (int i = 1; i <= cnt; i++)
            cout << ans[i].a << " " << ans[i].b << endl;
    }
 
    return 0;
 
}