gcd性质的利用——gcd区间

gcd区间的题目大概是这样的:

给定一串数列a[1..n],然后给出m次询问[l,r],求a[l..r]的所有数的gcd.

那么这道题的解法怎么办?

暴力的话就把题目给定的a数组记录下来,跑gcd.

像这样:

inline int gcd(int a,int b){
  int r;
  while (b){
    r=a%b;
    a=b;
    b=r;
  }
  return a;
}
inline int query(int L,int R){
  int r=a[L];
  for (int i=L+1;i<=R;i++)
    r=gcd(r,a[i]);
  return r;
}

很简单.

但在oj上不可能这么水一道题.

我们可以考虑优化方案.

我们考虑gcd的性质,预处理.

随便写个数据结构预处理就AC了.

但是我发现gcd满足重复计算不会出现误差的性质.

我们就可以用ST算法.

代码如下:

inline int gcd(int a,int b){
  int r;
  while (b){
  	r=a%b;
  	a=b;
  	b=r;
  }
  return a;
}
inline void start(){
  for (int i=1;i<=n;i++)
    r[i][0]=a[i];
  for (int j=1;(1<<j)<=n;j++)
    for (int i=1;i+(1<<j)-1<=n;i++)
      r[i][j]=gcd(r[i][j-1],r[i+(1<<(j-1))][j-1]);
}
inline int query(int L,int R){
  int len=int(log(R-L+1)/log(2));
  return (gcd(r[L][len],r[R-(1<<len)+1][len]));
}

就是这么简单.

比线段树要快还好写.

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/79693445
gcd