hdu 5207 Greatest Greatest Common Divisor【筛法】【思维】

本文介绍了一种在限定时间内寻找一组整数中任意两数的最大公约数的最大值的高效算法。通过枚举最大数的因子并检查其是否为多个数的因子来避免直接计算每对数的最大公约数。

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

Greatest Greatest Common Divisor

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1350    Accepted Submission(s): 562


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 integerT, indicating the number of test cases. For each test cases, the first line contains an integern, the size of the sequence. Next line contains n numbers, from a1 to an.1T100,2n105,1ai105. The case for n104 is no more than 10.
 


Output
For each test case, output one line. The output format is Case #x:ans,x is the case number, starting from 1,ans 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


这里暴力gcd是一定会TLE的、所以我们这里要应用一点小技巧、我们知道,如果一个数是a的因子数,并且也是b的因子数,那么这个数就叫a,b的公约数,这里我们可以枚举约数,而非每个数都求最大公约数、

首先 ,我们要做的事是要先找到这组数据中最大的那个:

        memset(ha,0,sizeof(ha));
        int n;
        int maxn=-0x1f1f1f1f;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int k;
            scanf("%d",&k);
            ha[k]++;
            maxn=max(maxn,k);
        }

这样我们就对所有的数据输入完毕,并且找到了这组数据最大的值maxn,那么我们知道,这组数据最大的因子数就是这个maxn,所以我们枚举因子数的时候,枚举到maxn就可以停了~

 

        int output=0;
        for(int i=1;i<=maxn;i++)//枚举因子数
        {
            int cont=0;
            for(int j=i;j<=maxn;j+=i)//找这个因子数的倍数,表明i是j的因子数
            {
                if(ha[j]==1)
                cont++;
                if(ha[j]>=2)output=j; 
            }
            if(cont>=2)//如果有i事两个以上数的因子数,那么它就是一个公约数,不一定这次是最大的,但是这样找下去总能找的到、
            output=max(output,i);
        }				

最后上完整的AC代码:

#include<stdio.h>
#include<iostream>
#include<string.h>
using namespace std;
int ha[100005];
int main()
{
    int kase=0;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(ha,0,sizeof(ha));
        int n;
        int maxn=-0x1f1f1f1f;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            int k;
            scanf("%d",&k);
            ha[k]++;
            maxn=max(maxn,k);
        }
        int output=0;
        for(int i=1;i<=maxn;i++)
        {
            int cont=0;
            for(int j=i;j<=maxn;j+=i)
            {
                if(ha[j]==1)
                cont++;
                if(ha[j]>=2)
                output=j;
            }
            if(cont>=2)
            output=max(output,i);
        }
        printf("Case #%d: %d\n",++kase,output);
    }
}








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值