[HDU 5726]GCD

Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

Problem Description

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

Input
The first line of input contains a number T 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 N integers, a1,...,an(0<ai1000,000,000).

The third line contains a number Q Q , denoting the number of queries.

For the next Q lines, i-th line contains two number , stand for the li,ri l i , r i , stand for the i 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') ( l ′ , r ′ ) such that gcd(al',al'+1,...,ar') g c d ( a l ′ , a l ′ + 1 , . . . , a r ′ ) equal gcd(al,al+1,...,ar) g c d ( a l , a l + 1 , . . . , a r ) .

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组询问,每组询问有两个数 l,r l , r 返回两个答案,
(1) gcd(a[i]) g c d ( a [ i ] ) (i[l,r]) ( i ∈ [ l , r ] )
(2)有多少对 [l,r] [ l ′ , r ′ ] 满足区间的最大公约数等于第一问

题解
第一问可以用rmq解决
那么问题是第二问,第二问我们可以经过一个预处理,处理出区间内所有可能出现的每个最大公因数所对应的区间个数。这个可以通过枚举区间左端点来解决,枚举区间左端点,然后以此为左端点有着连续、相同最大公因数的区间的右端点肯定是连续的,可以通过二分来确定他们的位置然后用map储存对应的最大公因数的区间个数就可以了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<map>
#include<cstdlib>
#include<cstring>
#define LiangJiaJun main
#define ll long long
using namespace std;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int n,m,a[100004];
map<int , ll >mert;
int gp[100004][24],mm[100004];
int pre(){
    mm[0]=-1;
    for(int i=1;i<=n;i++){
        mm[i]=((i&(i-1))==0)?mm[i-1]+1:mm[i-1];
        gp[i][0]=a[i];
    }
    for(int j=1;j<=mm[n];j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            gp[i][j]=gcd(gp[i][j-1],gp[i+(1<<(j-1))][j-1]);
        }
    }
    return 0;
}
int ask(int x,int y){
    int k=mm[y-x+1];
    return gcd(gp[x][k],gp[y-(1<<k)+1][k]);
}

int w33ha(int CASE){
    mert.clear();
    memset(gp,0,sizeof(gp));
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    pre();
    for(int i=1;i<=n;i++){
        int mid,l,r,now=a[i],rb=i;
        while(rb<=n){
            l=rb;r=n;int cpr=-1;
            while(l<=r){
                mid=(l+r)>>1;
                if(ask(i,mid)==now){
                    cpr=mid;l=mid+1;
                }
                else r=mid-1;
            }
            mert[now]+=cpr-rb+1;
            rb=cpr+1;
            now=gcd(now,a[rb]);
        }
    }
    printf("Case #%d:\n",CASE);
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        int l,r;scanf("%d%d",&l,&r);
        int g=ask(l,r);
        printf("%d %lld\n",g,mert[g]);
    }
    return 0;
}
int LiangJiaJun (){
    int T;scanf("%d",&T);
    for(int i=1;i<=T;i++)w33ha(i);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值