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) .
Solution
这种类型的题目多校很多,挑道简单的讲讲
首先以
l
为左端点,区间的不同
那么我们可以枚举一个
l
,不断然后向右二分,把
考虑到
gcd
的性质,可以考虑用ST表维护区间
gcd
那么
W
就变成了单个
Code
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb push_back
#define ph push
#define fi first
#define se second
inline void Max(int &a,int b){if(a<b)a=b;}
inline void Min(int &a,int b){if(a>b||a==-1)a=b;}
template<class T>void rd(T &a){
a=0;char c;
while(c=getchar(),!isdigit(c));
do a=a*10+(c^48);
while(c=getchar(),isdigit(c));
}
template<class T>void nt(T x){
if(!x)return;
nt(x/10);
putchar(48+x%10);
}
template<class T>void pt(T x){
if(!x)putchar('0');
else nt(x);
}
const int M=1e5+5;
const int S=21;
int A[M],g[M][S],_,txt,q,lg2[M],n;
inline int gcd(int n,int m){return m?gcd(m,n%m):n;}
inline void Init(){
int Mx=0;
for(int i=0;1<<i<M;++i)
lg2[1<<i]=i,Mx=i;
if(!lg2[M-1])lg2[M-1]=Mx+1;
for(int i=M-1;i;--i)
if(!lg2[i])lg2[i]=lg2[i+1];
lg2[1]=0;
}
inline int query(int l,int r){
int k=lg2[r-l+2]-1;
return gcd(g[l][k],g[r-(1<<k)+1][k]);
}
map<int,ll>mp;
inline void pret(){
for(int i=1;i<=n;++i)
g[i][0]=A[i];
for(int j=1;(1<<j)<=n;++j)
for(int i=1;i+(1<<j)-1<=n;++i){
g[i][j]=gcd(g[i][j-1],g[i+(1<<j-1)][j-1]);
}
for(int s=1;s<=n;++s){//左端点
for(int w=s;w<=n;){
int val=query(s,w),ans=n+1;
for(int mid,l=w,r=n;l<=r;){
mid=l+r>>1;
if(query(s,mid)!=val)r=mid-1,ans=mid;
else l=mid+1;
}//得到最远的gcd相同的位置+1
mp[val]+=ans-w;
w=ans;
}
}
}
inline void gao(){
printf("Case #%d:\n",++txt);
cin>>n;
mp.clear();
for(int i=1;i<=n;++i)rd(A[i]);
for(cin>>q,pret();q--;){
int l,r,k;rd(l),rd(r);
pt(k=query(l,r));
putchar(' ');
pt(mp[k]);
putchar('\n');
}
}
//#define LOCAL
int main(){
#ifdef LOCAL
freopen("data.in","r",stdin);
freopen("check.out","w",stdout);
#endif
for(cin>>_,Init();_--;)gao();
return 0;
}