HDU 5726 GCD(RMQ+二分)

GCD

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5303    Accepted Submission(s): 1909


 

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).

扫描二维码关注公众号,回复: 2877855 查看本文章

 

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个数,m次查询(n,m<=1e5)。每次查询l,r 问区间a[l]~a[r]的GCD为多少,和有多少个区间(l1,r1)gcd和a[l]~a[r]的gcd相等。

思路:很久没单独写过rmq了,趁简单题写一下。首先用RMQ处理出任意区间的GCD,然后对于每一个起点i的值,二分从i开始的区间的gcd可以延伸到多远,然后对于每一个变了的gcd,继续二分直到n。这里由于gcd每次至少/2,而a[i]<=1e9,所以不会超过30次。然后答案用map保存就可以了。注意可能会爆int,所以用long long。这样预处理的时间复杂度是O(nlogn),查询是O(logn)。有不理解或者疑惑的地方欢迎评论。

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+10;
int f[maxn][20],a[maxn];
int n,m;
int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}
void rmq()
{
    for(int i=1;i<=n;i++)f[i][0]=a[i];
    for(int i=1;i<20;i++)
    for(int j=1;j<=n;j++)
    if(j+(1<<i)-1<=n) f[j][i]=gcd(f[j][i-1],f[j+(1<<i-1)][i-1]);
}
int query(int l,int r)
{
    int k=(int)log2((double)(r-l+1));
    return gcd(f[l][k],f[r-(1<<k)+1][k]);
}
map<int,long long>mp;
void go()
{
    mp.clear();
    for(int i=1;i<=n;i++)
    {
        int g=f[i][0],j=i;
        while(j<=n)
        {
            int l=j,r=n;
            while(l<r)
            {
                int mid=(l+r+1)>>1;
                if(query(i,mid)==g) l=mid;
                else r=mid-1;
            }
            mp[g]+=l-j+1;
            j=l+1;
            g=query(i,j);
        }
    }
}
int main()
{
    int T,cas=1;
    scanf("%d",&T);
    while(T--)
    {
        printf("Case #%d:\n",cas++);
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        rmq();
        go();
        scanf("%d",&m);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            int t=query(x,y);
            printf("%d %lld\n",t,mp[t]);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/LSD20164388/article/details/81735928