D. CGCDSSQ
time limit per test 2 seconds
memory limit per test 256 megabytes
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.
Examples
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
题目大意:
一个长度为n的a数列,q次询问。每次询问一个数值x,求解有多少个[l,r](1<=l<=r<=n)满足Gcd(a[l],a[l+1],……,a[r])为x。
其中n<=1e5,q<=3e5,任意x,a[i]满足1<=x,a[i]<=1e9;
题解:
显然,对于每个询问我们都不得不枚举每个左端点,然后查询满足条件的右端点区间,然而在线超时,所以我们可以把询问用map记录,离线处理。又数组为静态,我们只需要静态维护一下区间最大公约数。同时把统计得到的每个询问结果累加即可。
#include<cstdio> #include<map> typedef long long ll; const int N=(int)1e6+10; inline void read(int &x){ x=0;char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(!(ch<'0'||ch>'9')) x=x*10+ch-48,ch=getchar(); } int n,m; int gcd(int x,int y){return y==0?x:gcd(y,x%y);} std::map<int ,ll > query; int a[N],lg[N],bin[20]; int f[20][N]; inline int ques(int l,int r){ if(r==n+1) return 0; int t=lg[r-l+1]; return gcd(f[t][l],f[t][r-bin[t]+1]); } inline void init(){ lg[0]=-1;for(int i=1;i<=n;i++)lg[i]=lg[i>>1]+1; bin[0]=1;for(int i=1;i<=18;i++) bin[i]=bin[i-1]<<1; for(int i=1;i<=n;i++) f[0][i]=a[i]; for(int i=1;i<=lg[n];i++) for(int j=1;j+bin[i]<=n+1;j++){ f[i][j]=gcd(f[i-1][j],f[i-1][j+bin[i-1]]); } } inline int find(int x,int l,int op){ int r=n+1; while(l<r-1){ int mid=l+r>>1; if(ques(op,mid)!=x) r=mid; else l=mid; } return l; } inline void solve(int x){ int t=a[x],now=x; int last; while(now!=n+1){ last=now; now=find(t,now,x); if(query[t])query[t]+=now-last+1; now++;t=ques(x,now); } } int x[N]; int main(){ read(n); for(int i=1;i<=n;i++) read(a[i]); read(m); init(); for(int i=1;i<=m;i++){ read(x[i]); query[x[i]]=1; } for(int i=1;i<=n;i++)solve(i); for(int i=1;i<=m;i++) printf("%I64d ",query[x[i]]-1); //while(1); }