HDU 5726 GCD(DP+线段树)

来源:互联网 发布:java queue线程安全 编辑:程序博客网 时间:2024/06/05 17:44

给定一个序列,对于每次查询,有多少个连续的子序列gcd等于x到y的序列的gcd


an记录不同gcd的数目,cot为滚动map用来记录第i-1位为终止位置的子区间的gcd的种类和数目,然后处理出所有lr范围内的gcd的数目

然后对于每次查询的lr的gcd,用线段树查询一下就好了


#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <map>#include <stack>#include <queue>#include <string.h>#include <string>#include <iomanip>#include <cstring>#include <vector>#include <functional>#include <cmath>#include <sstream>#include <set>using namespace std;#define PI acos(-1.0)#define sp system("pause")typedef long long ll;typedef unsigned long long ull;const ll mod = 1000000007;#define PI acos(-1.0)int tree[100000 * 4 + 20];vector<int>v;int gcd(int a, int b){return b == 0 ? a : gcd(b, a%b);}void build_tree(int l, int r, int now){if (l == r)tree[now] = v[l-1];else{int mid = (l + r) >> 1;build_tree(l, mid, now << 1);build_tree(mid + 1, r, now << 1 | 1);tree[now] = gcd(tree[now << 1], tree[now << 1 | 1]);}}int query(int l, int r,int now,int ql,int qr){if (l == ql&&r == qr)return tree[now];else{int mid = (l + r) >> 1;if (qr <= mid)return query(l, mid, now << 1, ql, qr);else if (ql > mid)return query(mid + 1, r, now << 1 | 1, ql, qr);else return gcd(query(l, mid, now << 1, ql, mid), query(mid + 1, r, now << 1 | 1, mid + 1, qr));}}int main(){int T;cin >> T;int cot = 1;while (T--){printf("Case #%d:\n", cot++);int n;map<int, ll>cot[2];map<int, ll>an;v.clear();cin >> n;int pos = 0;for (int i = 0; i < n; i++){int x;scanf("%d", &x);v.push_back(x);map<int, ll>::iterator po;for (po = cot[pos].begin(); po != cot[pos].end(); po++){int cc = gcd(po->first, x);cot[pos^1][cc] += cot[pos][po->first];an[cc] += cot[pos][po->first];}cot[pos].clear();cot[pos^1][x]++;an[x]++;pos ^= 1;}build_tree(1, n, 1);int m;cin >> m;while (m--){int x, y;scanf("%d%d", &x, &y);int ans = query(1, n, 1, x, y);printf("%d %lld\n", ans, an[ans]);}}}


0 0