思路:首先要知道的是不同区间的GCD会随着右端点延伸GCD是单调不增的,那么考虑枚举左端点,然后二分当前GCD看看最多能延伸到哪里,然后统计当前GCD数量,可以先把所有区间GCD预处理出来然后用map存,因为公因子不会太多
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000+500;
#define LL long long
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int dgcd[maxn][20];
int d[maxn];
map<int,LL>ans;
int res[maxn];
void init(int n,int d[])
{
for(int i = 1;i<=n;i++)
dgcd[i][0]=d[i];
for(int j = 1;(1<<j)<=n;j++)
for(int i = 1;i+(1<<j)-1<=n;i++)
dgcd[i][j]=gcd(dgcd[i][j-1],dgcd[i+(1<<(j-1))][j-1]);
}
int getgcd(int L,int R)
{
int k = 0;
while((1<<(k+1)) <= R-L+1)
k++;
return gcd(dgcd[L][k],dgcd[R-(1<<k)+1][k]);
}
int main()
{
int T,cas=1;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
for(int i = 1;i<=n;i++)
scanf("%d",&d[i]);
init(n,d);
int q;
scanf("%d",&q);
for(int i = 1;i<=q;i++)
{
int L,R;
scanf("%d%d",&L,&R);
res[i]=getgcd(L,R);
ans[res[i]]=0;
}
for(int i = 1;i<=n;i++)
{
int np = i;
while(np<=n)
{
int num = getgcd(i,np);
int l = np,r = n;
int cnt = 0;
while(l<=r)
{
int mid = (l+r)/2;
if(getgcd(i,mid)==num)
{
l = mid+1;
cnt = mid;
}
if(getgcd(i,mid)<num)
r = mid-1;
else
l = mid+1,cnt=mid;
}
ans[num]+=cnt-np+1;
np = r+1;
}
}
printf("Case #%d:\n",cas++);
for(int i = 1;i<=q;i++)
printf("%d %lld\n",res[i],ans[res[i]]);
}
}
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
Author
Source
2016 Multi-University Training Contest 1