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

2016 Multi-University Training Contest 1 1004 GCD HDU 5726 (RMQ)

2016-07-22 12:12 549 查看
http://acm.hdu.edu.cn/showproblem.php?pid=5726

题目大意:

给你一串数,然后在给你多个区间让你求这个区间内的数的gcd

以及这整串数和这个区间gcd相等的子序列有多少个。

第一个问题求gcd很容易的吶

long long gcd(long long a,long long b)
{
return a%b?gcd(b,a%b):b;
}


第二个问题需要求区间可以选择线段树。

这里安利一个求区间的算法RMQ算法

因为gcd是不增数列所以可以用到这个方法

先设A[]为题目给出的数串用样例1为代表

A[]={1,2,4,6,7};

然后我们设 a[i][j]数组为区间i到2^j之间的数的gcd值

所以

a[1][0]=1;a[1][1]=gcd(1,2);a[1][2]=gcd(1,2,4,6);

a[2][0]=2;a[2][1]=gcd(2,4);a[3][1]=gcd(4,6)

可以看出

a[2][1]=gcd(a[2][0],a[3][0]);

a[1][2]=gcd(a[1][1],a[3][1]);

从上可以推出状态转移方程

void rmq(long long num)
{

for(int j=0;j<30;j++)
for(int i=1;i<=num&&i+(1<<j)-1<=num;i++)
{
if(j==0)
ans[i][j]=a[i];
else ans[i][j]=gcd(ans[i][j-1],ans[i+(1<<j-1)][j-1]);//状态转移方程
}
}


最后结果进行二分就可以了

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<map>
#include<math.h>
#define M 100006
using namespace std;
long long ans[M][40];
long long a[M];
map<int,long long>q;
long long gcd(long long a,long long b) { return a%b?gcd(b,a%b):b; }
void rmq(long long num) { for(int j=0;j<30;j++) for(int i=1;i<=num&&i+(1<<j)-1<=num;i++) { if(j==0) ans[i][j]=a[i]; else ans[i][j]=gcd(ans[i][j-1],ans[i+(1<<j-1)][j-1]);//状态转移方程 } }
int find(int L,int R) //查找区间 区间长度为R-L+1
{
int k=log2(R-L+1);
return gcd(ans[L][k],ans[R-(1<<k)+1][k]);
}
int main()
{
int T;
int cas=0;
scanf("%d",&T);
while(T--)
{
printf("Case #%d:\n",++cas);
memset(ans,0,sizeof(ans));
long long g[M];
long long n;
scanf("%lld",&n);
int i,j,k;
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
}
rmq(n);
int m;
scanf("%d",&m);
for(i=1;i<=n;i++) //固定初始点
{
int st=i;
while(st<=n)
{
int t=0;
int head=st;
int ed=n;
int v=find(i,st);
while(head<=ed) //二分结果
{
int mid=(head+ed)/2;
int now=find(i,mid);
if(now==v)
{
t=mid;
head=mid+1;
}
else if(now<v)
{
ed=mid-1;
}
else
{
head=mid+1;
}
}
q[v]+=t-st+1;
st=ed+1;
}
}
while(m--)
{
int aa,b;
scanf("%d%d",&aa,&b);
int k=find(aa,b);
printf("%d %lld\n",k,q[k]);
}
q.clear();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: