####题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=5726
####题目大意:
对于一个序列,询问某个区间的gcd,和区间gcd与之相等的区间个数。
####解题思路:
之前做过区间内两两元素之间gcd和的题目,以为要用高级的数据结构,一直没有思路,看了标程,没有什么特殊的算法,就是记录类似前缀和的东西,还是对这种思路用的不够熟练。
标程的做法是:对于每个数字,记录从开始到当前数字的区间的子区间中以当前数字为结尾区间的gcd,相同gcd区间合并。具体过程看代码。这有一个知识点,一个百万级别的数大概有二百多个因子,所以109的因子也不会太多(没有证明,强行解释)。这样记录不会超内存。算法的复杂度应该在107左右 O(tn公因子个数)。
####代码:
/* ********************************
Author : danmu
Created Time : 2016年07月20日 星期三 04时08分39秒
File Name : d.cpp
******************************** */
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <string>
#include <vector>
#include <cstdio>
#include <stack>
#include <queue>
#include <cmath>
#include <list>
#include <map>
#include <set>
#define rep(i,x,y) for(int i=x;i<=y;++i)
#define _rep(i,x,y) for(int i=x;i>=y;--i)
#define CL(S,x) memset(S,x,sizeof(S))
#define CP (S1,S2) memcpy(S1,S2,sizeof(S2))
#define ALL(x,S) for(x=S.begin();x!=S.end();++x)
#define ULL unsigned long long
#define PI 3.1415926535
#define INF 0x3f3f3f3f
#define LL long long
const int maxn = 1e5+10;
const int mod = 1e9 + 7;
const double eps = 1e-8;
using namespace std;
int a[maxn];
vector<pair<int,int> > record[maxn];
map<int,LL> ans;
int gcd(int a,int b){
return b?gcd(b,a%b):a;
}
int main(){
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int t;
scanf("%d",&t);
for(int ca=1;ca<=t;++ca){
int n,q;
ans.clear();
scanf("%d",&n);
for(int i=0;i<=n;++i)
record[i].clear();
for(int i=1;i<=n;++i){
int last=0;
scanf("%d",a+i);
for(int j=0;j<record[i-1].size();++j){
int tmp=gcd(a[i],record[i-1][j].first);
if(tmp==last) continue;
last=tmp;
record[i].push_back(make_pair(tmp,record[i-1][j].second));
}
if(last!=a[i])
record[i].push_back(make_pair(a[i],i));
for(int j=0;j<record[i].size();++j)
ans[record[i][j].first]+=(j==record[i].size()-1?i+1:record[i][j+1].second)-record[i][j].second;
}
printf("Case #%d:\n",ca);
scanf("%d",&q);
for(int i=0;i<q;++i){
int u,v,j;
scanf("%d%d",&u,&v);
for(j=0;j<record[v].size();++j)
if(record[v][j].second>u)
break;
printf("%d %lld\n",record[v][j-1].first,ans[record[v][j-1].first]);
}
}
return 0;
}