Bootstrap

蓝桥杯2023年第十四届省赛真题-公因数匹配

题目来自DOPCPP:

公因数:一个能同时整数若干整数的整数。

暴力代码(超时):

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+10;

int n;
int arr[N];


signed main(){
    cin >> n;
    for(int i = 1 ;i <= n; i++) cin >> arr[i];
    //s表示方案中的起点  e表示终点
    //题目中说了 i < j 
    for(int i = 1; i <= n-1; i++){
        for(int j = i+1; j <= n; j++){
            //公因数:能同时整除若干整数的整数
            if(__gcd(arr[i], arr[j]) > 1){
                //更新答案
                cout << i << " " << j << endl;
                return 0;
            }
        }
    }
    return 0;
}

优化思路:

①找出每个数的公因数,存到map容器中。

②在枚举map容器中的公因数,找到每个公因数存的最小值,前两个就是i 和 j。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N = 1e5+10;

int n;
int arr[N];
//用来记录哪些书可以整除An
map<int, vector<int>>q;

//x表示枚举的An cnt表示在数组中的位置
void find(int x, int cnt){
    for(int i = 2; i<= x / i; i++){
        if(x % i != 0)continue;
        q[i].push_back(cnt);
        //去除重复的 i
        while(x % i == 0){
            x = x / i;
        }
    }
    //只被本身整除
    if(x > 1){
        q[x].push_back(cnt);
    }
    return;
}

signed main(){
    cin >> n;
    for(int i = 1; i <= n; i++){
        int x; cin >> x;
        //记录x可以被哪些数字整除
        find(x, i);
    }
    //答案
    int s=1e7, e = 1e7;
    //取出容器q中元素
    //x表示被这个数整除 y表示在数组中位置
    for(auto [x, y]: q){
        if(y.size() < 2)continue;
        // 1={1,3}
        // 2={1,2}
        //我们s,e先选择1,3 然后在下一组y[0] == s时候,可以更新e的最小值了
        //如果第一组的y[0]小于第二组的,我们的e不应该更新
        //我们s、e应该选择拥有相同公因数的最小值
        if(y[0] < s ||(y[0] == s && y[1] < e)){
            //前面两个数字最小
            s = y[0];
            e = y[1];
        }
    }
    cout << s << " " << e << endl;
    return 0;
}

;