• HDOJ 5726 GCD(RMQ+二分)


    Problem Description

    Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There are Q(Q≤100,000) queries. For each query l,r you have to calculate gcd(al,,al+1,...,ar) and count the number of pairs(l′,r′)(1≤l<r≤N)such that gcd(al′,al′+1,...,ar′) equal gcd(al,al+1,...,ar).

    Input

    The first line of input contains a number T, which stands for the number of test cases you need to solve.

    The first line of each case contains a number N, denoting the number of integers.
    The second line contains N integers, a1,...,an(0<ai≤1000,000,000).
    The third line contains a number Q, denoting the number of queries.
    For the next Q lines, i-th line contains two number , stand for the li,ri, stand for the i-th queries.

    Output

    For each case, you need to output “Case #:t” at the beginning.(with quotes, t means the number of the test case, begin from 1).

    For each query, you need to output the two numbers in a line. The first number stands for gcd(al,al+1,...,ar) and the second number stands for the number of pairs(l′,r′) such that gcd(al′,al′+1,...,ar′) equal gcd(al,al+1,...,ar).

    Sample Input

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

    Sample Output

    Case #1:
    1 8
    2 4
    2 4
    6 1 

    题意:

    有N个数,求第L个数到第R个数的最大公约数,并且求出任意区间内最大公约数为ans的数量。

    题解:

    对于区间[L,R],如果L固定不变,R不断右移时,gcd的值在不断下降,而且每次下降的幅度都不小于一半。我们只要枚举左端点L,然后二分L到N的区间,找到最大公约数为gcd的最大区间,记录这个gcd的数量并更新到map中即可。

    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int MAX=100005;
    int dp[MAX][20];
    int mm[MAX];
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    
    void initrmq(int n,int b[])
    {
        mm[0]=-1;
        for(int i=1;i<=n;i++)
        {
            mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
            dp[i][0]=b[i];
        }
        for(int j=1;j<=mm[n];j++)
            for(int i=1;i+(1<<j)-1<=n;i++)
                dp[i][j]=gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    }
    ll rmq(int x,int y)
    {
        int k=mm[y-x+1];
        return gcd(dp[x][k],dp[y-(1<<k)+1][k]);
    }
    
    ll find(int l,int r)
    {
        int k=(int)log2((double)(r-l+1));
        return gcd(dp[l][k], dp[r-(1<<k)+1][k]);
    }
    
    map<int,long long>ma;
    int main()
    {
        ios::sync_with_stdio(false);
        int T,n,ca=1,i,j;
        cin>>T;
        while(T--)
        {
            ma.clear();
            int b[MAX];
            cin>>n;
            for(i=1;i<=n;i++)
                cin>>b[i];
    
            initrmq(n,b);
            for(i=1;i<=n;i++)
            {
                int I=i;
                ll now=b[i];
                while(I!=n+1)
                {
                    int preI=I,N=n;
                    while(I!=N)
                    {
                        int mid=(I+N)/2+1;
                        if(find(I,mid)==now)
                            I=mid;
                        else N=mid-1;
                    }
                    ma[now]+=N-preI+1ll;
                    I++;
                    if(I!=n+1)
                        now=gcd(now,b[I]);
                }
            }
            cout<<"Case #"<<ca++<<":"<<endl;
            int q;
            cin>>q;
            for(i=1;i<=q;i++)
            {
                int l,r;
                cin>>l>>r;
                ll ans=rmq(l,r);
                cout<<ans<<" "<<ma[ans]<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    [fw]error: aggregate value used where an integer was expected
    [fw]awk求和
    [fw]谈EXPORT_SYMBOL使用
    [fw]用Kprobes调试(debug)内核
    [FW]使用kprobes查看内核内部信息
    linux缺頁異常處理--內核空間[v3.10]
    用C语言给指定的内存地址赋值(通过指针)
    [fw]Linux 的 time 指令
    how to prevent lowmemorykiller from killing processes
    Android成长日记-Noification实现状态栏通知
  • 原文地址:https://www.cnblogs.com/kannyi/p/9801346.html
Copyright © 2020-2023  润新知