直接枚举左端点,先找第一个 gcd 为左端点的区间,再找下一个使当前 gcd 不同的区间,但是Wa了,求助
#include<bits/stdc++.h>
using namespace std;
inline long long read()
{
char c (getchar());
long long x (0);
while (!isdigit(c)) c = getchar();
while (isdigit(c)) x = (x << 1) + (x << 3) + (c & 15) , c = getchar();
return x;
}
long long fa[100005][20];
int main()
{
int T (read());
while (T --)
{
const int n (read());
long long ans (0);
for (int i (1) ; i <= n ; ++ i)
{
fa[i][0] = read();
for (int j (1) ; j <= 19 ; ++ j)
fa[i][j] = 0;
}
for (int i (n - 1) ; i ; -- i)
for (int j (0) ; i + (1 << j + 1) - 1 <= n ; ++ j)
fa[i][j + 1] = __gcd(fa[i][j] , fa[i + (1 << j)][j]);
for (int l (1) ; l <= n ; ++ l)
{
long long now (fa[l][0]);
int R (l);
for (int i (19) ; i >= 0 ; -- i)
if (fa[R + 1][i] && fa[R + 1][i] % now == 0)
R += 1 << i;
ans = max(ans , (R - l + 1) * now);
for (int r (R + 1) ; r <= n ; r = R + 1)
{
R = r;
now = __gcd(now , fa[R][0]);
for (int i (19) ; i >= 0 ; -- i)
if (fa[R + 1][i] && fa[R + 1][i] % now == 0)
R += 1 << i;
ans = max (ans , (R - l + 1) * now);
}
}
printf("%lld\n" , ans);
}
return 0;
}