zoukankan      html  css  js  c++  java
  • HDOJ5726解题报告【ST表】

    题目地址:

      http://acm.hdu.edu.cn/showproblem.php?pid=5726

    题目概述:

      给出n个数以及q个询问,每个询问有两个数l,r,求[l,r]区间的gcd以及区间gcd等于这个gcd的所有方案数。

    大致思路:

      乍一看线段树,但是这个题询问太多了,所以我们使用ST表来做这个题目。

      区间max,min,gcd,lcm都可以用ST表来做,ST表在O(nlogn)的预处理之后,对每个询问的时间是O(1)的。

      而对于方案数,根据gcd不增的性质,我们可以枚举左端点,二分右端点,预处理所有的gcd对应的方案数。

    复杂度分析:

      ST表的处理是O(nlogn),方案数的预处理也是O(nlogn),而对于每个询问复杂度是O(1)。总的时间复杂度为O(T*nlogn)。

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <ctime>
    #include <map>
    #include <stack>
    #include <set>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    #define sacnf scanf
    #define scnaf scanf
    #define maxn 100010
    #define maxm 18
    #define inf 1061109567
    #define Eps 0.000001
    const double PI=acos(-1.0);
    #define mod 1000000007
    #define MAXNUM 10000
    #define For(i,j,k) for(int (i)=(j);(i)<=(k);(i)++)
    #define mes(a,b) memset((a),(b),sizeof(a))
    typedef long long ll;
    typedef unsigned long long ulld;
    void Swap(int &a,int &b) {int t=a;a=b;b=t;}
    ll Abs(ll x) {return (x<0)?-x:x;}
    
    int st[maxn][maxm],n,mk;
    map<int,ll> q;
    
    int gcd(int a,int b)
    {
        if(a<b) swap(a,b);
        return b?gcd(b,a%b):a;
    }
    
    int query(int l,int r)
    {
        int k=(int)log2((double)(r-l+1));
        return gcd(st[l][k],st[r-(1<<k)+1][k]);
    }
    
    void build_q()
    {
        for(int i=1;i<=n;i++)
        {
            int j=i,temp=st[i][0];
            while(j<=n)
            {
                int l=j,r=n;
                while(l<r)
                {
                    int m=(l+r+1)>>1;
                    if(query(l,m)==temp) l=m;
                    else r=m-1;
                }
                q[temp]+=(l-j+1);
                j=l+1;temp=query(i,j);
            }
        }
    }
    
    int main()
    {
        //freopen("data.in","r",stdin);
        //freopen("data.out","w",stdout);
        //clock_t st=clock();
        int T;scanf("%d",&T);
        For(kase,1,T)
        {
            printf("Case #%d:
    ",kase);mes(st,0);
            scanf("%d",&n);
            For(i,1,n) scanf("%d",&st[i][0]);
            for(int k=1;(1<<k)<=n;k++)
                For(i,1,n-(1<<k)+1) st[i][k]=gcd(st[i][k-1],st[i+(1<<(k-1))][k-1]);
            q.clear();build_q();
            int m,l,r;scanf("%d",&m);
            while(m--)
            {
                scanf("%d%d",&l,&r);
                int ans=query(l,r);
                printf("%d %I64d
    ",ans,q[ans]);
            }
        }
        //clock_t ed=clock();
        //printf("
    
    Time Used : %.5lf Ms.
    ",(double)(ed-st)/CLOCKS_PER_SEC);
        return 0;
    }
  • 相关阅读:
    算术异常
    MySQL和Oracle的区别
    string常用方法
    io异常
    关于null和空指针异常
    string的一些特殊点
    Mybatis中的动态SQL
    ORM框架的概述
    朴素贝叶斯分类器
    正则表达式
  • 原文地址:https://www.cnblogs.com/CtrlKismet/p/7137636.html
Copyright © 2011-2022 走看看