【JZOJ3780】【UVA1642】Magical GCD

题目大意:

给一个长度为 \(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);
}
posted @ 2020-03-15 03:50  Jayun  阅读(77)  评论(0编辑  收藏  举报