题目大意:
给一个长度为 \(n\) 的数列,找到一个连续子序列使得子序列的公约数与长度的乘积最大,求这个最大值。
正文:
直接枚举 GCD 区间的右端点 \(r\),再枚举左端点 \(l(l<r)\) 计算 GCD,记录答案。
\(\texttt{50}\) 分。
可以通过上一个枚举的右端点 \((r-1)\) 计算过的 GCD 区间更新当前区间就可以了,这些操作可以通过链表实现。
代码:
for (scanf ("%d", &t); t--; ) { memset (a, 0, sizeof(a)); memset (b, 0, sizeof(b)); memset (last_, 0, sizeof(last_)); memset (next_, 0, sizeof(next_)); ans = 0; scanf ("%lld", &n); for (int i = 1; i <= n; i++) { scanf ("%lld", &a[i]); b[i] = a[i]; last_[i] = i - 1, next_[i] = i + 1; } for (int r = 1; r <= n; r++) { for (int l = 1; l <= r; l = next_[l]) { b[l] = gcd(b[l], a[r]); ans = max(ans, (r - l + 1) * b[l]); if(b[l] == b[last_[l]]) { next_[last_[l]] = next_[l]; last_[next_[l]] = last_[l]; } } } printf("%lld\n", ans); }
来源:https://www.cnblogs.com/GJY-JURUO/p/12495769.html