HDU-2504

2018-12-25  本文已影响0人  Caproner

在此之前需要了解一下欧几里得算法,这是一个用于求最大公约数的算法。
事实上就是辗转相除法,你们可以翻一下你们的高中课本,或者直接百度查,都能够找到相关资料的。
那么这里假设你们能写欧几里得算法(不能的参考代码里的gcd函数就行了)。

在此之前,假设x和y的最大公约数表示为gcd(x,y)

首先要注意的是c不能等于b
有两种方法。
第一种比较简单,枚举c的值,从b+1开始从小到大一个一个枚举,直到满足条件位置。
为什么是从b+1开始呢?首先c不能等于b,其次,当c小于b的时候,由于gcd(a,c)必定是小于等于c的,所以其最大公约数不可能是b(因为gcd(a,c)<=c<b,所以gcd(a,c)<b)。所以c必定大于b。
那么知道这个的话代码就十分好写了:

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

LL gcd(LL a,LL b)
{
    if(b==0)return a;
    return gcd(b,a%b);
}

int main()
{
    int n;
    scanf("%d",&n);
    while(n--)
    {
        LL a,b;
        scanf("%lld%lld",&a,&b);
        LL c=b+1;
        while(gcd(a,c)!=b)c++;
        printf("%lld\n",c);
    }
    return 0;
}

用的时间是31ms:

image.png
第二种解法就相当于是扩展吧。要懂这个解法需要对最大公约数和素数(也叫质数)有一个比较充分的理解。
首先,由于gcd(a,c)=b,所以我们可以假设x和y使得:
#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

int Prime[8]={2,3,5,7,11,13,17,19};

int Solve(int a,int b)
{
    int p=a/b;
    for(int i=0;i<8;i++)
    {
        if(p%Prime[i]!=0)return Prime[i]*b;
    }
}

int main()
{ 
    int n;
    scanf("%d",&n);
    while(n--)
    {
        int a,b;
        scanf("%d%d",&a,&b);
        int c=Solve(a,b);
        printf("%d\n",c);
    }
    return 0;
}

这个代码的时间会比上面的代码少差不多一半时间:

上一篇 下一篇

猜你喜欢

热点阅读