Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
Problem Description
Give you a sequence of N(N≤100,000) N ( N ≤ 100 , 000 ) integers : a1,...,an(0<ai≤1000,000,000) a 1 , . . . , a n ( 0 < a i ≤ 1000 , 000 , 000 ) . There are Q(Q≤100,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')(1≤l<r≤N) ( 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 , denoting the number of integers.
The second line contains N N integers, .
The third line contains a number Q Q , denoting the number of queries.
For the next 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 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;
}