Primary Pair

题目描述

冰棍很喜欢高级的东西,他也觉得一些数学性质很"高级"。

冰棍有一个长为 n 的序列 {ai}\{a_i\}{ai}。他认为如果 aia_iaiaja_jaj 互质,那么 (i,j)(i,j)(i,j) 是一个高级数对。他想知道所有高级数对中的 i+ji+ji+j 最大是多少。

输入格式

输入第一行一个整数 T。

接下来 T 组数据,每组第一行一个数 n。

接下来一行 n 个空格分隔的正整数 aia_iai

输出格式

对于每组测试数据,输出一个整数,为满足条件的最大 i+ji+ji+j。若不存在符合条件的 i,ji,ji,j 则输出 −1-11

数据范围

对于 60%60\%60% 的数据,n≤100n \le 100n100
对于 100%100\%100% 的数据,1≤T≤101 \le T \le 101T102≤n≤2⋅1052 \le n \le 2 \cdot 10^52n21051≤ai≤10001 \le a_i \le 10001ai1000

样例

样例 1

输入:

6
3
3 2 1
7
1 3 5 2 4 7 7
5
1 2 3 4 5
3
2 2 4
6
5 4 3 15 12 16
5
1 2 2 3 6

输出:

6
12
9
-1
10
7

Primary Pair 题解

我的解题思路

我看到这道题的核心要求是:找到互质的数对,让它们的下标之和最大。而且数据范围很关键:数组长度最大 2e5,但数字大小最多只有 1000。

我是这么思考的:

  1. 数组很长,但数值很小,我不需要遍历所有数对,那样会超时。
  2. 我只需要记录每个数字最后出现的下标,因为下标越大,加起来的和就越大,这是最优的。
  3. 最后我只需要在 1~1000 这些数字里暴力枚举所有数对,判断是否互质,然后取最大下标和就行。

我的代码思路与逐行说明

我写的这段代码非常简洁高效,完全符合题目要求,下面是我的思路:

#include <bits/stdc++.h>
using namespace std;
int t,n,x;
int p[1005];  // 我用 p 数组存每个数字最后出现的下标,最多 1000
int main() {    
    cin>>t;    // 我读入测试数据组数
    while(t--){  // 每组数据循环处理
        cin>>n;
        memset(p,0,sizeof(p));  // 每次清空数组,避免上一组数据影响
        
        for(int i=1;i<=n;i++){  // 我遍历数组,记录每个数最后出现的下标
            cin>>x;
            p[x]=max(p[x],i);  // 只保留最大(最后)的下标,这是最优的
        }
        
        int ans=-1;  // 答案初始化为 -1,表示没有找到
        
        // 我暴力枚举 1~1000 所有数对
        for(int i=1;i<=1000;i++){
            for(int j=1;j<=1000;j++){
                if (p[i]==0||p[j]==0) continue;  // 没出现过的数字直接跳过
                if (__gcd(i,j)==1){  // 判断互质
                    ans=max(ans,p[i]+p[j]);  // 更新最大下标和
                }
            }
        }
        
        cout<<ans<<"\n";
    }
    return 0;
}

我设计的核心技巧

  1. 只存最后出现的下标
    我知道,下标越大,和就越大,所以我只保留每个数字最后一次出现的位置,前面的下标直接忽略。

  2. 利用数值范围小的特点
    数组长度 2e5 很大,但数字只有 1~1000,所以我只需要枚举 1000×1000=1e6 次,完全不会超时。

  3. 直接用 __gcd 判断互质
    我用系统自带的最大公约数函数,如果 gcd 等于 1,就说明两个数互质。

  4. 初始化答案为 -1
    如果没有任何互质对,直接输出 -1,符合题目要求。


我用样例测试的效果

以第一组样例输入为例:

3
3 2 1

我记录的最后下标:
3→1,2→2,1→3

我枚举所有互质对:
2 和 1 互质 → 2+3=5
3 和 1 互质 →1+3=4
3 和 2 互质 →1+2=3
最大是 6(3+3,数字1和1也互质)

最终输出 6,和样例一致。

所有样例我都能正确输出答案。


我的总结

我这段代码完美利用了数字范围小的特点,避开了暴力枚举数组的低效做法,只记录最优下标,然后在小范围内枚举。
代码时间复杂度极低、逻辑清晰、能通过所有测试点,完全不用修改就能直接 AC

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐