codeforces 475D CGCDSSQ ST表+二分

點擊打開鏈接鏈接

CGCDSSQ
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Given a sequence of integers a1, ..., an and q queries x1, ..., xq on it. For each query xi you have to count the number of pairs (l, r)such that 1 ≤ l ≤ r ≤ n and gcd(al, al + 1, ..., ar) = xi.

 is a greatest common divisor of v1, v2, ..., vn, that is equal to a largest positive integer that divides all vi.

Input

The first line of the input contains integer n, (1 ≤ n ≤ 105), denoting the length of the sequence. The next line contains n space separated integers a1, ..., an, (1 ≤ ai ≤ 109).

The third line of the input contains integer q, (1 ≤ q ≤ 3 × 105), denoting the number of queries. Then follows q lines, each contain an integer xi, (1 ≤ xi ≤ 109).

Output

For each query print the result in a separate line.

Sample test(s)
input
3
2 6 3
5
1
2
3
4
6
output
1
2
2
0
1
input
7
10 20 3 15 1000 60 16
10
1
2
3
4
5
6
10
20
60
1000
output
14
0
2
2
2
0
2
2
1
1
給出一串數字  q個查詢

問有幾對l r使得從l到r的gcd爲x

用線段樹會T

ST表 然後二分 

代碼如下

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define MAXN 111111
using namespace std;
int n,stgcd[MAXN][35],num[MAXN];
int prelog2[MAXN];
map<int ,long long > ans;
int gcd(int a,int b){
    if(b==0)
	return a;
    return gcd(b,a%b);
}
void init(){
    prelog2[1]=0;
    for(int i=2;i<=n;i++){
	prelog2[i]=prelog2[i-1];
	if((1<<prelog2[i]+1)==i)
	    prelog2[i]++;
    }
    for(int i=n;i>=1;i--){
	stgcd[i][0]=num[i];
	for(int j=1;(i+(1<<j)-1)<=n;j++){
	    stgcd[i][j]=gcd(stgcd[i][j-1],stgcd[i+(1<<j-1)][j-1]);
	}
    }
}
int getgcd(int l,int r){
    int len=r-l+1;
    return gcd(stgcd[l][prelog2[len]],stgcd[r-(1<<prelog2[len])+1][prelog2[len]]);
}
void solve(){
    for(int i=1;i<=n;i++){
	int ed=i,l,r,m,pos;
	while(ed<=n){
	    int xx=getgcd(i,ed);
	    l=ed,r=n,pos=-1;
	    while(l<=r){
		if(r-l<=1){
		    if(getgcd(i,r)==xx)
			pos=r;
		    else if(getgcd(i,l)==xx)
			pos=l;
		    break;
		}
		m=l+r>>1;
		if(getgcd(i,m)==xx)
		    l=m;
		else r=m;
	    }
	    ans[xx]+=pos-ed+1;
	    ed=pos+1;
	}
    }
}
int main(){
    int q,xx;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
	scanf("%d",&num[i]);
    init();
    solve();
    scanf("%d",&q);
    while(q--){
	scanf("%d",&xx);
	printf("%I64d\n",ans[xx]);
    }
    return 0;
}


發佈了94 篇原創文章 · 獲贊 4 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章