luogu1890 gcd区间
Posted headboy2002
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu1890 gcd区间相关的知识,希望对你有一定的参考价值。
题目大意:给定一行n个正整数a[1]..a[n]。m次询问,每次询问给定一个区间[L,R],输出a[L]..a[R]的最大公因数。
因为gcd满足交换律和结合律,所以用线段树维护区间上的gcd值即可。
#include <cstdio> #include <cstring> using namespace std; const int MAX_RANGE = 1010; int GetGcd(int a, int b) { return b ? GetGcd(b, a % b) : a; } struct GcdRangeTree { private: int Gcd[MAX_RANGE * 4]; int N; void PullUp(int cur) { Gcd[cur] = GetGcd(Gcd[cur * 2], Gcd[cur * 2 + 1]); } void Init(int cur, int sl, int sr, int *a) { if (sl == sr) { Gcd[cur] = a[sr]; return; } int mid = (sl + sr) / 2; Init(cur * 2, sl, mid, a); Init(cur * 2 + 1, mid + 1, sr, a); PullUp(cur); } int Query(int cur, int sl, int sr, int al, int ar) { //printf("cur(%d,%d) find(%d,%d)\n", sl, sr, al, ar); if (al <= sl && sr <= ar) return Gcd[cur]; int ans=0, mid = (sl + sr) / 2; if (al <= mid) ans = Query(cur * 2, sl, mid, al, ar); if (ar > mid) { if (ans) ans = GetGcd(ans, Query(cur * 2 + 1, mid + 1, sr, al, ar)); else ans = Query(cur * 2 + 1, mid + 1, sr, al, ar); } return ans; } public: GcdRangeTree(int n, int *a) { N = n; memset(Gcd, 0, sizeof(Gcd)); Init(1, 1, N, a); } int Query(int l, int r) { return Query(1, 1, N, l, r); } }; int main() { int range, opCnt; static int a[MAX_RANGE]; scanf("%d%d", &range, &opCnt); for (int i = 1; i <= range; i++) scanf("%d", a + i); static GcdRangeTree g(range, a); while (opCnt--) { int l, r; scanf("%d%d", &l, &r); printf("%d\n", g.Query(l, r)); } return 0; }
以上是关于luogu1890 gcd区间的主要内容,如果未能解决你的问题,请参考以下文章