• C++ P1890 gcd区间


    题目描述

    给定一行n个正整数a[1]..a[n]。

    m次询问,每次询问给定一个区间[L,R],输出a[L]..a[R]的最大公因数。

    输入输出格式

    输入格式:

    第一行两个整数n,m。

    第二行n个整数表示a[1]..a[n]。

    以下m行,每行2个整数表示询问区间的左右端点。

    保证输入数据合法。

    输出格式:

    共m行,每行表示一个询问的答案。

    输入输出样例

    输入样例#1: 

    5 3
    4 12 3 6 7
    1 3
    2 3
    5 5
    

    输出样例#1: 

    1
    3
    7
    

    说明

    对于30%的数据,n <= 100, m <= 10

    对于60%的数据,m <= 1000

    对于100%的数据,1 <= n <= 1000,1 <= m <= 1,000,000

                    0 < 数字大小 <= 1,000,000,000

    题目地址: https://www.luogu.org/problemnew/show/P1890


    个人思路:

    • 一开始打了个枚举获取答案的代码,虽然开了inline,并使用了scanf,但还是TLE了最后两个点.
    • 之后又尝试使用一个data[]数组,记忆化已经gcd得到的答案,仍然TLE,
    • 想了一下,只好看题解.题解的方法是预处理,然后O(1)查询.
    • 然后就自己思考了一下,之前也想过预处理,但是感觉复杂度可能太高了.
    • 但是题解中的预处理使用了gcd的一个传递性.假设我们要预处理的是a[i],则预处理存储数组data[i][j]=gcd(data[i][j-1])(因为j代表区间长度,代表起始点.然后通过最大公约数的性质即可求出答案)
    • 再思考一下时间复杂度,大约为O(n^2),又因为n的范围够小,所以这个时间复杂度可以接受.

    #include<cstdio>
    #include<iostream>
    using namespace std;
    int a[1000],data[1005][1005];
    inline int gcd(int a,int b){
        if(a<b)swap(a,b);;
        if(b==0)return a;
        return gcd(b,a%b);
    }
    int main(){
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++){
        	for(int j=i;j<=n;j++){
        		data[i][j]=gcd(data[i][j-1],a[j]);
    		}
    	}
        for(int i=1;i<=m;i++){
            int ta,tb;
            scanf("%d%d",&ta,&tb);
            printf("%d
    ",data[ta][tb]);
        }
        return 0;
    }
  • 相关阅读:
    python 5 条件判断
    python 4学习 list 和 tuple
    python 3 学习字符串和编码
    python 1 学习廖雪峰博客
    c++11 thread的学习
    C++ 11 Lambda表达式!!!!!!!!!!!
    c++11 右值的学习
    TreeMap
    二分查找
    solr in action 第三章
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680686.html
Copyright © 2020-2023  润新知