hdu5223(GCD)

题目链接:点击打开链接

题意:

首先给定数组中有多少个数,只告诉你他们最小值为1,不告诉你每个数字是多少,要求根据给定区间中数的最大公约数,复原原来的序列。

思路:

先把所有的数初始化为1,然后根据指定问题,如果某一区间的最大公约数是ans, 那么这个区间中的所有数字都是ans的倍数,所以,把区间中的每个数字都赋值为原数字和ans的最小公倍数即可。


这道题本来是一道水题,但由于自己的粗心而导致在比赛中一直是wrong answer。错误的原因就是数据类型用错了。首先看到数据范围是10的9次方,在int范围内(int范围是2的32次方比 4 乘以10的9次方多一点),所以我就考虑使用int行来保存数组中的所有数字,但由于在求最小公倍数是涉及到两个数的乘法,所以有可能会超出int的范围,本来很好处理的问题,但我竟然又声明了一个long long int 的变量用来保存两个int型数据的乘积,这样做是愚蠢的,因为两个int型数据相乘时结果还是int型,用long long int 保存两个int型数据的乘积就是先把两个int型数据相乘的到的int型结果强制转化为long long int 而已, 在相乘中就会出现超出范围的问题,即相乘的结果就是错误的,所以在赋值后,还是错误的。  

解决的办法应该是先把两个int型分别赋值到两个long long int型变量中,然后把两个long long int 型变量相乘后除以他们的最大公约数,最后检查 这个数是否越界,如果不越界就可以赋值给对应的int型变量了。

代码如下:

#include 
#include 
#include 

using namespace std;
const int MAXN= 1005;
int a[MAXN], l[MAXN], r[MAXN], ans[MAXN], n, q;
int gcd(int a, int b)
{
    int tem;
    while(b != 0)
    {
        tem = a % b;
        a = b;
        b = tem;
    }
    return a;
}
int scd(long long int a,long long int b)   //注意要用long long int 或 long int
{
        return (long long)(a*b)/gcd(a,b);
}
int newgcd(int l, int r)  //区间在l,r范围的最大公约
{
    long long int i, tem = a[l];
    for(i = l+1; i <= r; i++)
    {
        tem = gcd(tem, a[i]);
    }
    return tem;
}
void init(int num)
{
    int i;
    for(i = 1; i <= num+2; i++)
    {
        a[i] = 1;
    }
}
int main()
{
    int i, j, t;
    bool ok;
    long long int tem;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &n, &q);
        init(n);
        ok = true;
        for(i = 1; i <= q; i++)
        {
            scanf("%d%d%d", &l[i], &r[i], &ans[i]);
            if(ans[i] == 1)
                continue;
            for(j = l[i]; j <= r[i]; j++)
            {
		/*
                最初是这样求最小公倍数的
                tem = a[j] * ans[i];    //如果乘积超过整型的范围,赋值给tem的数还是错误的。
                a[j] = tem / gcd(a[j], ans[i]);
                */
                tem = scd(a[j], ans[i]);  //求最小公倍数
                if(tem > 1000000000)     //注意题中的条件,做题容易只考虑下界而不考虑上界。
                {
                    ok =false;
                    break;
                }
                else
                {
                    a[j] = tem;
                }
            }
        }
        if(ok != false)
        {
            for(i = 1; i <= q; i++)
            {
                if(newgcd(l[i], r[i]) != ans[i])
                {
                    ok = false;
                    break;
                }
            }
        }
        if(ok)
        {
            for(i = 1; i < n; i++)
            {
                printf("%d ", a[i]);
            }
            printf("%d\n", a[i]);
        }
        else
        {
            printf("Stupid BrotherK!\n");
        }
    }
    return 0;
}


109109


你可能感兴趣的:(数论)