题目描述
思路
考虑分治。
要求 的答案,之需求下面三部分答案的最大值(set ):
-
的答案;
-
的答案;
-
的答案最大值。
这样前两者可以递归解决,考虑如何解决最后一个。
经典结论:一个序列的前缀(后缀) 最多有 种取值。
那么我们可以预处理 的每个不同的后缀 的下标的最小值, 的每个不同的前缀 的下标的最大值。然后只需要枚举即可。
时间复杂度为
设 为时间复杂度。
根据 master 定理,
代码
#include <bits/stdc++.h>
using namespace std;
namespace io {
const int SIZE = (1 << 21) + 1;
char ibuf[SIZE], *iS, *iT, obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[55]; int f, qr;
// getchar
#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)
// print the remaining part
inline void flush () {
fwrite (obuf, 1, oS - obuf, stdout);
oS = obuf;
}
// putchar
inline void putc (char x) {
*oS ++ = x;
if (oS == oT) flush ();
}
// input a signed integer
template <class I>
inline void read (I &x) {
for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;
for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x *= f;
}
// print a signed integer
template <class I>
inline void print (I x) {
if (!x) putc ('0'); if (x < 0) putc ('-'), x = -x;
while (x) qu[++ qr] = x % 10 + '0', x /= 10;
while (qr) putc (qu[qr --]);
}
struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: print;
const int MAXN = 1e5 + 10;
typedef long long ll;
int T, n;
ll a[MAXN];
vector<pair<ll, int> > p1, p2;
ll Solve(int l, int r) {
if (l == r) return a[l];
if (l > r) return 0;
int mid = l + r >> 1;
ll res1 = Solve(l, mid), res2 = Solve(mid + 1, r), res3 = 0;
p1.clear(); p2.clear();
ll tmp1 = a[mid], tmp2;
for (int i = mid - 1; i >= l; i--) {
tmp2 = __gcd(tmp1, a[i]);
if (tmp2 != tmp1) {
p1.push_back({tmp1, i + 1});
tmp1 = tmp2;
}
}
p1.push_back({tmp1, l});
tmp1 = a[mid + 1];
for (int i = mid + 2; i <= r; i++) {
tmp2 = __gcd(tmp1, a[i]);
if (tmp2 != tmp1) {
p2.push_back({tmp1, i - 1});
tmp1 = tmp2;
}
}
p2.push_back({tmp1, r});
for (auto i : p1) {
for (auto j : p2) {
res3 = max(res3, __gcd(i.first, j.first) * (ll)(j.second - i.second + 1));
}
}
return max({res1, res2, res3});
}
int main () {
read(T);
while (T--) {
read(n);
for (int i = 1; i <= n; i++) read(a[i]);
print(Solve(1, n));
putc('\n');
}
return 0;
}