###题目:
http://acm.hdu.edu.cn/showproblem.php?pid=5726
###AC代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <map>
#include <string>
#include <cstring>
#include <algorithm>
#define maxn 100000 + 10
using namespace std;
typedef long long LL;
LL a[maxn];
LL n;
LL N,M,K,T,t,q;
LL d[maxn][18];
LL gcd(LL a,LL b)
{
if (b==0) return a;
else return gcd(b,a%b);
}
void predig()
{
memset(d,0,sizeof(d));
for (LL i = 0; i<n; i++)
{
d[i][0] = a[i];
}
for (LL j = 1; (1 << j) <= n; j++)
{
for (LL i = 0; (i + (1 << j) - 1)<n; i++)
{
d[i][j] = gcd(d[i][j - 1], d[i + (1 << (j - 1))][j - 1]);
}
}
return;
}
LL rmq(LL l, LL r)
{
l--;
r--;
LL k = 0;
while (1 << (k + 1) <= (r - l + 1)) k++;
return gcd(d[l][k], d[r - (1 << k) + 1][k]);
}
LL Fr(LL _gcd, LL i)
{
LL st = i,ed = n-1;
while(ed - st >= 1)
{
LL mid = st + ed >> 1;
if (gcd(rmq(i+1,mid+1),_gcd) >= _gcd) st = mid + 1;
else ed = mid - 1;
}
if(gcd(rmq(i+1,st+1),_gcd) != _gcd) st--;
return st;
}
void solve()
{
predig();
map<LL,LL> mq;
for(LL i = 0; i < n; i++)
{
LL _gcd = a[i];
LL pos = i;
while(pos<n)
{
LL pos1 = Fr(_gcd,pos);
mq[_gcd] += pos1 - pos + 1;
pos = pos1 + 1;
_gcd = gcd(_gcd,a[pos]);
}
}
scanf("%lld",&q);
printf("Case #%d:\n",t);
while(q--)
{
LL L,R,ans;
scanf("%lld%lld",&L,&R);
ans = rmq(L,R);
printf("%lld %lld\n",ans,mq[ans]);
}
return ;
}
int main()
{
cin >> T;
for(t = 1; t <= T; t++)
{
memset(a,1,sizeof(a));
scanf("%lld",&n);
for (LL i = 0; i < n; i++)
scanf("%lld",&a[i]);
solve();
}
}
###题解:
1.RMQ && ST——GCD
2.GCD
3.区间二分