• 2020牛客多校第四场H


    题意:

    在{1,2,3,...,n}中找到两个没有交集的序列使得gcd(ai, bi)>1,即找到ai和bi两两配对,使得他们不互质

    思路:

    显而易见,> n/2的素数是不能配对的。我们可以先把1~n的素数筛出来,从大到小枚举每个素数p(从小到大会漏)。

    对于每个素数p,2p,3p,...... ,kp (k == n / p)两两配对,如果k为奇数,则把2p留下。

    最后把留下的偶数两两配对,得到最终答案。

    Code:

    #pragma GCC optimize(3)
    #pragma GCC optimize(2)
    #include <map>
    #include <set>
    #include <array>
    #include <queue>
    #include <stack>
    #include <cmath>
    #include <vector>
    #include <cstdio>
    #include <cstring>
    #include <sstream>
    #include <iostream>
    #include <stdlib.h>
    #include <algorithm>
    #include <unordered_map>
    
    using namespace std;
    
    typedef long long ll;
    typedef pair<int, int> PII;
    
    #define Time (double)clock() / CLOCKS_PER_SEC
    
    #define sd(a) scanf("%d", &a)
    #define sdd(a, b) scanf("%d%d", &a, &b)
    #define slld(a) scanf("%lld", &a)
    #define slldd(a, b) scanf("%lld%lld", &a, &b)
    
    const int N = 2e5 + 10;
    const ll M = 4e12;
    const int mod = 1e9 + 7;
    
    int t;
    int n, cnt;
    int primes[N];
    bool st[N], vis[N];
    vector<pair<int, int>> v;
    
    
    void get(int n)
    {
        cnt = 0;
        for (int i = 2; i <= n; i++)
        {
            if (!st[i])
                primes[cnt++] = i;
            for (int j = 0; primes[j] <= n / i; j++)
            {
                st[primes[j] * i] = true;
                if (i % primes[j] == 0)
                    break;
            }
        }
    }
    
    int main()
    {
    #ifdef ONLINE_JUDGE
    #else
        freopen("/home/jungu/code/in.txt", "r", stdin);
        // freopen("/home/jungu/code/out.txt", "w", stdout);
    #endif
        // ios::sync_with_stdio(false);
        cin.tie(0), cout.tie(0);
    
        sd(t);
        get(N - 10);
        while (t--)
        {
            sd(n);
    
            for (int i = 1; i <= n; i++)
            {
                vis[i] = false;
            }
            v.clear();
    
            int num = -1, a, b;
            for (int i = n / 2; i >= 2; i--)
            {
                if(st[i]) continue;
    
                if(i > n / 2) continue;
                int k = n / i * i;  
    
                for( ; k >= 0; k -= i){
                    while(vis[k] && k >= 0){
                        k -= i;
                    }
                    if(k == 0){
                        break;
                    }
                    vis[k] = true;
                    a = k;
                    while(vis[k] && k >= 0){
                        k -= i;
                    }
                    if(k == 0){
                        break;
                    }
                    vis[k] = true;
                    if(k == 2 * i){
                        if(num == -1){
                            num = k;
                        }
                        else{
                            v.push_back({k, num});
                            num = -1;
                        }
                        k -= i;
                        vis[k] = true;
                    }
                    v.push_back({a, k});
    
                }
                
            }
            printf("%d
    ", (int)v.size());
            for(auto x : v){
                printf("%d %d
    ", x.first, x.second);
            }
        }
    
        return 0;
    }
  • 相关阅读:
    shell 指定范围产生随机数
    shell脚本比较两个数大小
    Shell 脚本实现随机抽取班级学生
    linux通过挂载系统光盘搭建本地yum仓库的方法
    kuberenetes 上使用helm部署rancher如何卸载干净
    Windows 下 左Ctrl和Caps交换
    C#笔记 -- 协变、逆变
    Python 读取window下UTF-8-BOM 文件
    生成命令行程序使用脚本
    ffmpeg 命令小记
  • 原文地址:https://www.cnblogs.com/jungu/p/13347999.html
Copyright © 2020-2023  润新知