【JZOJ3780】【UVA1642】Magical GCD

题目大意:

给一个长度为 (n) 的数列,找到一个连续子序列使得子序列的公约数与长度的乘积最大,求这个最大值。

正文:

直接枚举 GCD 区间的右端点 (r),再枚举左端点 (l(l<r)) 计算 GCD,记录答案。

( exttt{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
", ans);
}
原文地址:https://www.cnblogs.com/GJY-JURUO/p/12495769.html