您的位置:首页 > 大数据 > 人工智能

2016 Multi-University Training Contest 1 T4

2016-07-20 15:46 519 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5726

求不修改区间gcd可以用线段树或者倍增。

求l-n的我们注意观察gcd(a​l​​,a​l+1​​,...,a​r​​),当l固定不动的时候,r=l...n时,我们可以容易的发现,随着r的増大,gcd(a​l​​,a​l+1​​,...,a​r​​)是递减的,同时gcd(a​l​​,a​l+1​​,...,a​r​​)最多 有log 1000,000,000个不同的值,因为a​l​​最多也就有log 1000,000,000个质因数。

然后我们用链表记录所有gcd改变的点,这些点将l...n这一段分成若干个相同gcd的区间。由l...n的gcd关系可以推出l-1...n的gcd关系。相邻区间gcd相同时将两个区间合并。用map统计gcd是x的区间有多少个。

#include<cstdio>
#include<cstring>
#include<map>
#define N 100010
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
int te,l[N*4],r[N*4],a[N*4],f
,x
;
long long j,n,nex
;
int t,m,ans,ll,rr,num,i,_;
map<int,long long> sc;

int gcd(int aa,int bb)
{
int tt,a=aa,b=bb;
while (a%b!=0)
{
tt=a;
a=b;
b=tt%b;
}
return b;
}
void build(int s,int ll,int rr)
{
l[s]=ll;r[s]=rr;
if (ll==rr)
{
scanf("%d",&x[++num]);
a[s]=x[num];
}
else
{
build(s*2,ll,(ll+rr)/2);
build(s*2+1,(ll+rr)/2+1,rr);
a[s]=gcd(a[s*2],a[s*2+1]);
}
}
void sea(int s)
{
if (l[s]>rr || r[s]<ll) return;
if (ll<=l[s] && rr>=r[s])
if (ans==-1)
ans=a[s];
else
ans=gcd(ans,a[s]);
else
{
sea(s*2);
sea(s*2+1);
}
}
int main()
{
scanf("%d",&_);
while (_--)
{
printf("Case #%d:\n",++te);
num=0;
mem(f);sc.clear();mem(nex);mem(l);mem(r);mem(a);
scanf("%d",&n);
build(1,1,n);
f
=x
;sc[x
]++;
for (i=n-1;i>=1;i--)
{
j=i+1;
while (j!=0)
{
f[j]=gcd(f[j],x[i]);
j=nex[j];
}
f[i]=x[i];
nex[i]=i+1;
j=i;
while (nex[j]!=0)
{
if (f[j]==f[nex[j]])
nex[j]=nex[nex[j]];
else
j=nex[j];
}
j=i;
while (j!=0)
{
if (nex[j]==0)
sc[f[j]]+=n-j+1;
else
sc[f[j]]+=nex[j]-j;
j=nex[j];
}

}
scanf("%d",&m);
for (t=1;t<=m;t++)
{
scanf("%d%d",&ll,&rr);
ans=-1;
sea(1);
printf("%d %I64d\n",ans,sc[ans]);
}
}
return 0;
}


View Code
Run IDSubmit TimeJudge StatusPro.IDExe.TimeExe.MemoryCode Len.LanguageAuthor
176434452016-07-20 14:35:10Accepted57261950MS14112K1557BG++lbz007
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: