码迷,mamicode.com
首页 > 其他好文 > 详细

hdu5371 RGCDQ

时间:2015-07-28 21:16:48      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:acm   hdu   

首先计算出所有的f,这里容易超时,注意优化:先计算出所有质数,然后在利用这些质数去求f。 易知f中的最大值为7,然后用一个数组b[i][j]记录f[1]到f[i]中有多少个j(j 为1到7),这个用递推可得。 那么如果给定区间L, R, 则f[R][j] - f[L - 1][j]可算出1到7各出现了多少次, 根据这些次数就可以找出最大公约数了。代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int MAXN = 1000002;
int prime[MAXN + 1], f[MAXN], b[MAXN][8], bb[8];;
void getprime()   //先计算区间内的所有质数,提高计算效率。
{
    memset(prime, 0, sizeof(prime));
    for(int i = 2; i <= MAXN; i++)
    {
        if(!prime[i]) prime[++prime[0]] = i;
        for(int j = 1; j <= prime[0] && prime[j] <= MAXN/ i; j++)
        {
            prime[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}
int getFactors(int tmp)  //计算质因子的个数。
{
    int fatCnt = 0;
    for(int i = 1; prime[i] <= tmp/prime[i]; i++)
    {
        if(tmp % prime[i] == 0)
        {
            while(tmp % prime[i]== 0)
                tmp /= prime[i];
            fatCnt++;
        }
    }
    if(tmp  != 1)
    {
       fatCnt++;
    }
    return fatCnt;
}
int gcd(int a, int b)
{
    while(b != 0)
    {
        int tem = a % b;
        a  = b;
        b = tem;
    }
    return a;
}
int getAns()  //根据区间中f值的情况输出结果。
{
    int i, j, ans = 1;
    for(i = 7; i >= 1; i--)
    {
        if(!bb[i])
            continue;
        for(j = i; j >= 1; j--)
        {
            if(j == i)
            {
                if(bb[i] > 1)
                    ans = max(ans, j);
                continue;
            }
            if(bb[j] >= 1)
                ans = max(ans, gcd(i, j));
        }
    }
    return ans;
}
int main()
{
    int i, j;
    getprime();
    for(i = 2; i <= MAXN; i++)
        f[i] = getFactors(i);
    for(i = 2; i <= MAXN; i++)
    {
        for(j = 1; j <= 7; j++)
            b[i][j] = b[i-1][j];
        b[i][f[i]]++;
    }

    int l, r, t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &l, &r);
        memset(bb, 0, sizeof(bb));
        for(i = 1; i <= 7; i++)
        {
            bb[i] = b[r][i] - b[l-1][i];     //bb记录区间内f值的情况。
        }
        printf("%d\n", getAns());
    }
    return 0;
}

 

hdu5371 RGCDQ

标签:acm   hdu   

原文地址:http://blog.csdn.net/yanzheshi/article/details/47109353

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!