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])); }
就是这么简单.
比线段树要快还好写.