2015 HDU 多校联赛 5317 RGCDQ 筛法求解

2015 HDU 多校联赛 5317 RGCDQ 筛法求解

题目  http://acm.hdu.edu.cn/showproblem.php?

pid=5317

本题的数据量非常大,測试样例多。数据量大, 所以必须做预处理。也就是用筛法求出全部的F[x],将全部F[x] 打印出来发现。事实上结果不大,最大的数值是7。所以对于每一个区间询问, 直接暴力求取有多少个 1 2 3 4 5 6 7 就可以,从大到小查找。假设出现2个以上 3-7 的数值,那么最大公约数就是该数字。

假设没有出现两个反复的。那么结果要么是 3 (3,6) 要么是 2 (2,4)。 (4。 6), (2,6) 。假设都不是。那么就是 1。

我认为本题主要难点在筛法求F[x] 上。

#include <bits/stdc++.h>

using namespace std;

const int MAX = 1000000+2;
bool vis[MAX];
int f[MAX];
int s[8][MAX];

inline void init()  // O(nlngn)
{
    // 素数筛法 获取 f(x)
    for(int i=2; i<MAX; ++i)
    {
        if (!vis[i])  // 没有被筛去
        {
            f[i]++; // 自身是素数,自增

            // 筛去i的倍数。 同一时候将f[i的倍数]++。由于i的倍数值,肯定含有i 这个质因子
            for(int j=i+i; j<MAX; j+=i)
            {
                f[j]++;
                vis[j] = true;  // 筛去
            }
        }
    }

    // 统计区间 2-i 各有多少个 1 2 3 4 5 6 7
    for(int i=2; i<MAX; ++i)
    {
        for(int j=1; j<=7; ++j)
        {
            s[j][i] = s[j][i-1];    // 取上一次的结果
            if (f[i] == j)  // 当前值能够进行累加
                s[j][i]++;
        }
    }
}

inline int getMaxGCD(int l, int r)
{
    int arr[8] = {};
    for(int i=1; i<=7; ++i)
    {
        arr[i] = s[i][r] - s[i][l-1];
    }

    // 是否有2个以上的情况
    for(int i=7; i>2; --i)
    {
        if (arr[i] >= 2)
            return i;
    }

    // 处理单个的情况
    if (arr[3]+arr[6] >= 2)
        return 3;

    if (arr[2]+arr[4]+arr[6] >= 2)
        return 2;

    return 1;
}

int main(void)
{
    //freopen("in.txt", "r", stdin);

    init();

    int t = 0;
    scanf("%d", &t);
    while(t--)
    {
        int l, r;
        scanf("%d%d", &l, &r);
        printf("%d\n", getMaxGCD(l, r));
    }

    return 0;
}

另外在杭电上。也有一道类似的题目, 主要考察筛法。

题目  http://acm.hdu.edu.cn/showproblem.php?pid=1215

// 数据量特别大,一定要做预处理

#include <bits/stdc++.h>

using namespace std;

const int MAX = 500000+2;
int ans[MAX] = {};

inline void init()
{
    ans[1] = 1;
    for(int i=2; i<MAX; ++i)
    {
        ans[i]++;
        for(int j=i+i; j<MAX; j+=i)
        {
            ans[j] += i;
        }
    }
}

int main(void)
{
    //freopen("in.txt", "r", stdin);

    init();

    int t, n;
    cin>>t;
    while(t--)
    {
        scanf("%d", &n);
        printf("%d\n", ans[n]);
    }

    return 0;
}

測试用例数量非常大且数据量大的时候。应该做预处理

时间: 2024-10-08 10:27:58

2015 HDU 多校联赛 5317 RGCDQ 筛法求解的相关文章

2015 HDU 多校联赛 5326 Work

2015 HDU 多校联赛 5326 Work 题目: http://acm.hdu.edu.cn/showproblem.php?pid=5326 这题应该是本周二多校赛中,最简单的一道题目了. 解题思路: 就是回根. 用一个数组 root[i] = j 表示 i 的上级是 j , 对于每个输入的关系都做这样的处理.然后遍历每个编号直到root[i] 的结果为0 (因为根没有上级,所以根为0),在往根回退的过程中,用一个数组 cnt[i] 表示经过i这个点的次数. 最后就是遍历 cnt[i],

2015 HDU 多校联赛 5363 Key Set

2015 HDU 多校联赛 5363 Key Set 题目: http://acm.hdu.edu.cn/showproblem.php?pid=5363 根据前面给出的例子,得出求解公式 fn = 2^(n-1) - 1, 数据量大,实际就是求幂次方. 可用分治法求解,复杂度O(nlogn) // 分治法求快速幂 #include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; const int MO

hdu 5317 RGCDQ 筛法+线段树解法

RGCDQ Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 299    Accepted Submission(s): 151 Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more and mor

hdu 5344 (多校联赛) MZL&#39;s xor --- 位运算

here:    首先看一下题吧:题意就是让你把一个序列里所有的(Ai+Aj) 的异或求出来.(1<=i,j<=n) Problem Description MZL loves xor very much.Now he gets an array A.The length of A is n.He wants to know the xor of all (Ai+Aj)(1≤i,j≤n) The xor of an array B is defined as B1 xor B2...xor B

HDU 5317 RGCDQ (合数分解+预处理)

题目链接:HDU 5317 RGCDQ 题意:定义函数F(x)为x的不同的素因子且小于等于x的个数,询问[l,r]区间中gcd(F(i),F(j))的最大值. 思路:暴力预处理出所有的合数分解结果,发现F(x)最大也只有7,之后就是暴力求出所有1到7出现次数的前缀和.询问的时候就打到O(1)了. AC代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #

[2015hdu多校联赛补题]hdu5371 Hotaru&#39;s problem

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5371 题意:把一个数字串A翻过来(abc翻过来为cba)的操作为-A,我们称A-AA这样的串为N-sequence,现在给你一个数字串,问你这个串中最长的N-sequence子串长度 解:可以想到A-A是一个回文串,-AA也是一个回文串,那么首先Manacher跑一遍求出所有回文子串 可以想到任意两个互相覆盖的回文子串都可以表示成N-sequence 然后有三种搞法: 1.时间复杂度O(N*logN

[2015hdu多校联赛补题]hdu5348 MZL&#39;s endless loop

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题意:给你一个无向图,要你将无向图的边变成有向边,使得得到的图,出度和入度差的绝对值小于等于1,如果无解输出-1 解:考虑奇数度的点一定会成对出现(因为所有度数和肯定是偶数个->因为一条边产生两度~),那么我们可以将奇数度的点两两一连消除掉(两奇数度点的出度入读差的绝对值都为1, 路径上的点的差绝对值为0) 然后偶数度的点可以成环,那么可以搜出所有的环 1 /* 2 * Problem: 3

HDU多校赛第9场 HDU 4965Fast Matrix Calculation【矩阵运算+数学小知识】

难度上,,,确实,,,不算难 问题是有个矩阵运算的优化 题目是说给个N*K的矩阵A给个K*N的矩阵B(1<=N<=1000 && 1=<K<=6),先把他们乘起来乘为C矩阵,然后算C^(N*N) 相当于 ABABABABABABAB...=(AB)^(N*N) 不如 A(BA)^(N*N-1)B 因为BA乘得K*K的矩阵,K是比较小的 #include <cstdio> #include <cstdlib> #include <cstr

2014 HDU多校弟八场H题 【找规律把】

看了解题报告,发现看不懂 QAQ 比较简单的解释是这样的: 可以先暴力下达标,然后会发现当前数 和 上一个数 的差值是一个 固定值, 而且等于当前数与i(第i个数)的商, 于是没有规律的部分暴力解决,有规律的套公式 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <cstring&g