Greatest Greatest Common Divisor

本文介绍了一道ACM竞赛题目的解决方案,旨在从一组整数中找出两个数的最大公因数之最值。通过巧妙地利用数组记录数值出现频次,并遍历可能的公因数进行统计,最终高效地找到了答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Greatest Greatest Common Divisor

 
 Accepts: 271
 
 Submissions: 1138
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
Problem Description

Pick two numbers ai,aj(ij) from a sequence to maximize the value of their greatest common divisor.

Input

Multiple test cases. In the first line there is an integer T, indicating the number of test cases. For each test cases, the first line contains an integer n, the size of the sequence. Next line contains n numbers, from a1 to an1T100,2n105,1ai105. The case for n104 is no more than 10.

Output

For each test case, output one line. The output format is Case #xansx is the case number, starting from 1ans is the maximum value of greatest common divisor.

Sample Input
2
4
1 2 3 4
3
3 6 9
Sample Output
Case #1: 2
Case #2: 3
小结:
  说起来,好久没有刷ACM的题目了,感觉久违的第一题竟然是如此的令人绝望,看来如果不努力就要不断地被人超越了呢,还真是感触很深呢。
  题目的大概意思就是在n个数中,找到最大公因数最大的一对数,并且输出这个最大公因数。
  第一反应就感觉这道题目不是可以用暴力可以求解的题目,如果枚举的话,时间复杂度是n^2以上,都不用提交就知道肯定是TLE,然后第一反应就是用杨氏筛法筛取一个区间内的所有素数的方法,然而感觉那个方法我可能记得太清楚了,反而限制了我的思维,真是惭愧啊!
  接着就是求援的过程了,参考了前辈的代码之后,才发现了题目中有一点我完全没看清楚,数的范围是10^5,数的个数是10^5,然后就写出了最后的代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;


int num[100010];//这个数组储存的是输入的所有的数,其实也不需要专门开数组来储存==
int ans[100010];//这个数组储存的是每个下角标作为公因数出现了几次
int a[100010];//这个数组储存的是输入的所有数,范围中有则记录为1,否则为0
void solve(int n)
{
    memset(ans,0,sizeof(ans));
    for(int i=2;i<=n;i++)//i为待测的公因数
    {
        for(int j=i;j<=n;j+=i)//对于范围内的i的倍数进行检验,如果存在i的倍数,则对于i进行改变
        {
            ans[i]+=a[j];
        }
    }
}
int main()
{
    int n;
    int ma;
    int t;//t为测试组数
    scanf("%d",&t);
    for(int m=1;m<=t;m++)
    {
        ma=0;//ma储存的是输入所有数中的最大值
        scanf("%d",&n);//n储存的是输入数的个数
        memset(a,0,sizeof(a));//数组的初始化
        memset(num,0,sizeof(num));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&num[i]);
            a[num[i]]++;
            ma=max(ma,num[i]);
        }
        solve(ma);
        ans[1]=2;
        for(int i=ma;i>=1;i--)//对因数的逆序检查,并且输出
        {
            if(ans[i]>=2)//当ans的值大于等于2时,说明存在一对以上的数的公因数为i
            {
                printf("Case #%d: %d\n",m,i);
                break;
            }
        }
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值