因为case输出后要换行,被PE了一发……
因为map多组数据没初始化,又WA了一发……哎
题目大意
给定n个数字, 问[L,R]区间的所有数字的gcd是多少。如果是K的话, 有多少个区间的gcd也是K。
做法:计算区间GCD的问题,求K的话,显然是线段树啊,ST算法都能解决。这里不再赘述。
然后就是根据题解的思想~~
g[i][] 表示第i(从1开始计数,不是从0开始)个数字为区间起点,随着区间的终点往右推进,可以得到哪些gcd的值。
举个例子,数列4 9 6 6 3 2
以9为起点,那么
g[2][]里保存的就是9,3,3,3,1. 因为分别为【9】 【9 6】【9 6 6】【9 6 6 3】【9 6 6 3 2】
因为【显然】,这个g数组里的元素值是单调递减的~ 所以我们不需要记录那么多3,只要记录有多少个6就可以了。
比如还是上面的例子,g[2][0] = 一个9 g[2][1] = 3个3, g[2][2] = 一个1。 也就是说,保存的数字数量是log级的。
对于求g[1][]的值的时候,很方便,可以直接利用g[2]里保存的元素直接求出。 因为gcd求解满足结合律。。相当于先求后面的,再和4(数列的第一个元素)求一下gcd。
这样求解就很快,也是log级别的。
最后我们在求解的过程中已经保存了诸如“一个9, 3个3”这样的数据,都存起来,到时候问问题的时候,直接查就行了。(我用的是map)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
#include <vector>
#include <map>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
const int maxn = 100020;
const int maxnode = maxn * 4;
int n, m;
LL a[maxn];
vector<LL>g[maxn];
vector<LL>w[maxn];
map<LL, LL>mp;
LL gcd(LL a, LL b)
{
return a%b?gcd(b,a%b):b;
}
void init()
{
scanf("%d", &n);
for (int i = 0; i <= n; ++ i)
{
g[i].clear();
w[i].clear();
}
mp.clear();
for (int i = 1; i <= n; ++ i)
scanf("%lld", &a[i]);
}
inline void ins(LL t, LL p)
{
if (mp.find(t) == mp.end()) mp[t] = p;
else mp[t] += p;
}
LL gd[maxnode];
void build(int o, int L, int R)
{
if (L == R)
{
gd[o] = a[L];
return ;
}
int M = L + (R- L) / 2;
int lc = o * 2, rc = o * 2 + 1;
build(lc, L, M);
build(rc, M + 1, R);
gd[o] = gcd(gd[lc], gd[rc]);
}
int ql, qr;
LL ans;
void query(int o, int L, int R)
{
if (ql <= L && R <= qr)
{
ans = gcd(ans, gd[o]);
return;
}
int M = L + (R -L) / 2;
int lc = o * 2, rc = o * 2 + 1;
if (ql <= M) query(lc, L, M);
if (qr > M) query(rc, M + 1, R);
}
void doit()
{
g[n].push_back(a[n]);
w[n].push_back(1);
ins(a[n], 1);
for (int i = n - 1; i >= 1; -- i)
{
g[i].push_back(a[i]);
w[i].push_back(1);
ins(a[i], 1);
LL tmp = a[i];
for (int j = 0; j != g[i + 1].size(); ++ j)
{
LL t = g[i + 1][j];
LL num = w[i + 1][j];
t = gcd(tmp, t);
if (t != tmp)
{
tmp = t;
g[i].push_back(tmp);
w[i].push_back(num);
}else
{
w[i][w[i].size() - 1] += num;
}
ins(tmp, num);
}
}
scanf("%d", &m);
build(1, 1, n);
while (m--)
{
scanf("%d%d", &ql, &qr);
ans = a[ql];
query(1, 1, n);
printf("%lld %lld\n", ans, mp[ans]);
}
}
int main()
{
int T;
scanf("%d", &T);
for (int i = 1; i <= T; ++i)
{
printf("Case #%d:\n", i);
init();
doit();
}
return 0;
}
/*
4
3 3
##G
G##
###
1.7959
*/