2023年第十四届省赛真题-公因数匹配,详细讲解以及分解质因数

问题描述

给定 n 个正整数 Ai​,请找出两个数 i,j 使得 i<j 且 Ai 和 Aj 存在大于 1 的公因数。

如果存在多组 i,j请输出 ii 最小的那组。如果仍然存在多组 i,j请输出 i最小的所有方案中 j 最小的那组。

输入格式

输入的第一行包含一个整数 n。

第二行包含 n 个整数分别表示 A1​,A2,……,An​,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含两个整数分别表示题目要求的 i,j用一个空格分隔。

暴力:

函数__gcd(),双层for循环,保证i<j;遇到第一个就return 0;

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
int n;
int nums[N];
 
int main(){
    cin >> n;
    for(int i = 1 ;i <= n; i++) cin >> nums[i];
    
    for(int i = 1; i <= n-1; i++){
        for(int j = i+1; j <= n; j++){
         
            if(__gcd(nums[i], nums[j]) > 1){
            
                cout << i << " " << j << endl;
                return 0;//直接结束程序运行
            }
        }
    }
    return 0;
}

AC:

我们可以写一个分解质因数的算法,并且定义一个map容器,前面存质因数,后面存数组的角标,然后用for循环保证数组角标是由小到大即可。

#include<iostream>
#include<algorithm>
#include<vector>
#include<map>
using namespace std;
map<int,vector<int>>st;//前面是质因数,后面是角标数组
int n=0;
int nums[501000];


int main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) 
        cin >> nums[i];
    
    for (int i = 1; i <= n; i++)//找公因数,角标存入
    {
        for (int j = 2; j <= nums[i] / j; j++)//一个数的质因数不会超过他的平方根
            if (nums[i] % j == 0)
            {
                st[j].push_back(i);
                while (nums[i] % j == 0) {//保证公因数都是质数
                    nums[i] /= j;
                }
            }
        if (nums[i] > 1)//本身就是一个质因数
            st[nums[i]].push_back(i);
    }
    pair<int, int>ans = {100000000,100000000};
    for (auto [x,y] : st) {
        if (y.size() < 2) 
            continue;
        if (y[0] < ans.first) {
            ans = { y[0], y[1] };
        }
        else if (y[0] == ans.first) {
            if (y[1] < ans.second) {
                ans = { y[0], y[1] };
            }
        }
    }
    cout << ans.first << " " << ans.second << endl;

}

这里稍微说一个分解质因数的算法,先传入一个数X,然后令i=2,进行质因数循环判断,如果取余运算等于0,那么这个i就是这个质因数,再写一个while循环让他一直分解,直到没有位置,最后如果大于一,那么他本身就是一个质数。循环的终止条件是一个数的质因数不会超过他的平方根。

还有这个auto的用法,如果auto后加&符号,我们可以修改遍历的对象,如果不加就不能修改。但是加了之后会影响代码运行的效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值