题目链接
A1、...、(0 <ai≤1000,000,000):あなたはNのシーケンス(N≤100,000)整数を与えます。Q(Q≤100,000)クエリがあります。各クエリリットルの場合は、(1≤l<r≤N)ようにGCD(アル"あなたは計算GCD(アル、アル+ 1、...、AR)を持っており、ペア(L '、R')の数をカウントrを、ら'+ 1、...、Ar'は)等しいGCD(AL、ら+ 1、...、AR)。
入力
入力の最初の行は、あなたが解決する必要があるテストケースの数を表して数Tを、含まれています。
それぞれの場合の最初の行は、整数の数を示す、番号Nを含有します。
2行目はNの整数、A1、...、(0 <ai≤1000,000,000)を含みます。
第三のラインは、クエリの数を表す、数値Qを含んでいます。
次のQラインの場合は、i番目の行は2つの番号、李用のスタンド、Riは、i番目のクエリに立つ含まれています。
出力
各ケースに対しては、あなたが出力する必要があります。:先頭に「ケース#T」(引用符で、tはテストケースの数を意味し、1から始まります)。
各クエリについて、次の行に出力するように2つの数値を必要とします。最初の番号は、(AL、ら+ 1、...、AR)GCDを表し、2番目の数字は対(L '、R')の数を表すようにGCD(AL '、アル' + 1、...、Ar 'は)同じGCD(AL、ら+ 1、...、AR)。
サンプル入力
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
サンプル出力
ケース#1:
1 8
2 4
2 4
6 1
著者の
HIT
ソース
2016マルチ大学研修コンテストザ・1つの
アイデア:私たちは木のラインを見つけることができ間隔GCDが、それを要求するか、同じ数の?列挙が可能であるので、我々は、サブインターバルN内の長GCDの数がよりログより確実でないことを知っているときに列挙[I] [前に1、[それを横断するときI- 1] GCDデマンド型とカウント数、クエリがO(1)であってもよいです。例えば、[I-1]〜1既にGCDのxは、今GCD(X、[I])は、Y次に、yに等しく、[CNT] +のGCDに固有の番号(X)に等しいです。番号、それをマッピングするマップと、その後GCD預金。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+1;
ll a[maxn];
ll gcd (ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
struct node{
int l,r;
ll num;
}tree[maxn<<2];
map<ll,ll>p1,p2,cnt;
void build(int l,int r,int x)
{
tree[x].l=l,tree[x].r=r;
if(l==r){
tree[x].num=a[l];return ;
}
int mid=(l+r)>>1;
build(l,mid,x<<1);
build(mid+1,r,x<<1|1);
tree[x].num=gcd(tree[x<<1].num,tree[x<<1|1].num);
}
ll query(int x,int l,int r)
{
if(l==tree[x].l&&tree[x].r==r) return tree[x].num;
int mid=(tree[x].l+tree[x].r)>>1;
if(r<=mid) return query(x<<1,l,r);
else if(l>mid) return query(x<<1|1,l,r);
else return gcd(query(x<<1,l,mid),query(x<<1|1,mid+1,r));
}
int main()
{
int T,n,m,l,r;
scanf("%d",&T);
for(int j=1;j<=T;++j)
{
printf("Case #%d:\n",j);
scanf("%d",&n);
p1.clear(),p2.clear(),cnt.clear();
for(int i=1;i<=n;++i)
{
scanf("%lld",&a[i]);
cnt[a[i]]++;
p2[a[i]]++;
for(auto it=p1.begin();it!=p1.end();it++)
{
ll t=gcd(a[i],it->first);
cnt[t]+=it->second;
p2[t]+=it->second;
}
p1.clear();
for(auto it=p2.begin();it!=p2.end();it++) p1[it->first]=it->second;
p2.clear();
}
build(1,n,1);
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&l,&r);
ll ans=query(1,l,r);
printf("%lld %lld\n",ans,cnt[ans]);
}
}
}