P1890 gcd区间 - st表

st表细节多。。。
用线段树维护也行,会慢一点
最大公约数这个东西区间上是“可加”的
所以可以很方便地合并出区间gcd
注意位运算优先级低,多加括号

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
const int MAXN =  1000000 + 10;
int n,m,st[MAXN][25],a[MAXN];
int gcd(int a, int b) {
	return b == 0 ? a : gcd(b, a%b);
}
void init_st() {
	int mt = log(n) / log(2) + 1;
	for(int k=1; k<=mt; k++) {
		for(int i=1; i+(1<<k)-1<=n; i++) {
			st[i][k] = gcd(st[i][k-1], st[i+(1<<k-1)][k-1]);
		}
	}
}
int query(int l, int r) {
	int kt = log(r-l+1) / log(2);
	return gcd(st[l][kt], st[r-(1<<kt)+1][kt]);
}
int main() {
	scanf("%d%d", &n, &m);
	for(int i=1; i<=n; i++) {
		scanf("%d", &a[i]);
		st[i][0] = a[i];
	}
	init_st();
	for(int i=1; i<=m; i++) {
		int l, r;
		scanf("%d%d", &l, &r);
		printf("%d\n", query(l, r));
	}
	return 0;
}
posted @ 2018-10-16 20:47  Zolrk  阅读(231)  评论(0编辑  收藏  举报