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) .
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
题意:编号1到n的数列,给定了l,r 的区间,求区间的gcd,并求与此gcd相同的区间个数
思路:RMQ 统计区间的gcd,枚举左端点,二分求右端点的长度
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#define LL long long
using namespace std;
#pragma comment(linker, "/STACK:102400000000,102400000000")
int T;
int n,m;
const int N=100007;
int a[N];
int mm[50];
int dp[N][50];
map<int,LL> mp;
int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
void initRMQ(int n,int a[])
{
mm[0]=-1;
for(int i=1;i<=n;i++)
{
mm[i]= ((i&(i-1)) == 0 ) ? mm[i-1]+1 : mm[i-1];
dp[i][0] = a[i];
}
for(int j=1;j<=mm[n];j++)
for(int i=1;i+(1<<j)-1 <= n;i++)
dp[i][j] = gcd(dp[i][j-1],dp[i+ (1<<(j-1))][j-1]);
}
int rmq(int l,int r)
{
int k=mm[r-l+1];
return gcd(dp[l][k],dp[r - (1<<k) + 1][k]);
}
int main()
{
int cas=1;
int l,r;
scanf("%d",&T);
while(T--)
{
mp.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
initRMQ(n,a);
// for(int i = 1; i < n+1; i++)
// {
// int l = i-1,r = n+1;
// while(l+1 < n+1)
// {
// int st = rmq(i,l+1);
// int pre = l;
// while(l+1 < r)
// {
// int mid = (l+r)/2;
// int gg = rmq(i,mid);
// if(gg >= st)
// l = mid;
// else
// r = mid;
// }
// LL cnt = l - pre;
// if(mp.find(st) == mp.end())
// mp[st] = 0;
// mp[st] += cnt;
// r = n+1;
// }
// }
int ss,st,pre;
int l,r,mid;
for(int i=1;i<=n;i++)
{
l=i,r=n+1,mid;
while(l<r)
{
st = rmq(i,l);
pre = l;
while(l+1<r)
{
mid = (l+r)/2;
ss = rmq(i,mid);
if(ss >= st)
l = mid;
else
r = mid ;
}
LL cnt = l - pre + 1;
l++;
if( mp.find(st) == mp.end() )
mp[st] = 0;
mp[st]+=cnt;
r=n+1;
}
}
printf("Case #%d:\n",cas++);
scanf("%d",&m);
int ans=0;
for(int i=0;i<m;i++)
{
scanf("%d%d",&l,&r);
int tt= rmq(l,r);
printf("%d %I64d\n",tt,mp[tt]);
}
}
return 0;
}