GCD
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.
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).
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
分析:因为固定左端点的GCD对右端点而言单调不增,所以可以二分。RMQ可以预处理所有区间的GCD;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <map> #include <queue> #include <stack> #include <vector> #include <list> #include <ext/rope> #define rep(i,m,n) for(i=m;i<=n;i++) #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++) #define vi vector<int> #define pii pair<int,int> #define mod 1000000007 #define inf 0x3f3f3f3f #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) const int maxn=1e5+10; const int dis[4][2]={{0,1},{-1,0},{0,-1},{1,0}}; using namespace std; using namespace __gnu_cxx; int gcd(int p,int q){return q==0?p:gcd(q,p%q);} ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;} int n,m,a[maxn],p[maxn],st[20][maxn]; map<int,ll>ans; void all_init() { for(int i=2;i<=maxn-10;i++)p[i]=1+p[i/2]; } void init() { for(int i=1;i<20;i++) for(int j=1;j+(1<<i)-1<=n;j++) st[i][j]=gcd(st[i-1][j],st[i-1][j+(1<<(i-1))]); } int getgcd(int l,int r) { int x=p[r-l+1]; return gcd(st[x][l],st[x][r-(1<<x)+1]); } int work(int now,int l,int start) { int pos,r=n; while(l<=r) { int mid=l+r>>1; if(getgcd(start,mid)>=now) pos=mid,l=mid+1; else r=mid-1; } return pos; } int main() { int i,j,k,t; all_init(); scanf("%d",&t); for(k=1;k<=t;k++) { ans.clear(); scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&st[0][i]); init(); for(i=1;i<=n;i++) { for(j=i;j<=n;) { int q=getgcd(i,j),ending; ending=work(q,j,i); ans[q]+=ending-j+1; j=ending+1; } } printf("Case #%d:\n",k); scanf("%d",&m); while(m--) { int l,r; scanf("%d%d",&l,&r); j=getgcd(l,r); ll num=ans[j]; printf("%d %lld\n",j,num); } } //system ("pause"); return 0; }