P9032 [COCI2022-2023#1] Neboderi

可以发现,如果固定 ll,那么 gcd(al,al+1,,ar)\gcd(a_l, a_{l+1}, \cdots, a_r) 显然单调递减。

接着可以发现,ll 固定时,随着 rr 的增大,gcd\gcd 的不同个数并不多。

可以这样理解:如果 gcd\gcd 不同个数很多,那就意味着每次增大 rr 的时候,ara_r 分解质因数后都会有一个质因数的次数变小。而质因数的次数变小很快就会变回 11

所以固定 ll,二分 rr 的变化点即可并且 ST 表维护区间 gcd\gcd 即可。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <numeric>
#include <vector>
using namespace std;

const int N = 1e6 + 5;

int n, k, a[N];
long long ans = 0, sum[N];

int f[N][31], LG2[N];

void Init()
{
	LG2[1] = 0;
	for (int i = 2; i < N; i++) LG2[i] = LG2[i >> 1] + 1;
	for (int i = 1; i <= n; i++)
	{
		f[i][0] = a[i];
	}
	for (int j = 1; j <= LG2[n]; j++)
	{
		for (int i = 1; i + (1 << j) - 1 <= n; i++)
		{
			f[i][j] = gcd(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
		}
	}
}

int query(int l, int r)
{
	int x = LG2[r - l + 1];
	return gcd(f[l][x], f[r - (1 << x) + 1][x]);
}

int main()
{
	scanf("%d%d", &n, &k);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]), sum[i] = sum[i - 1] + a[i], ans = max(ans, 1LL * a[i]);
	Init();
	for (int i = 1; i <= n - k + 1; i++)
	{
		int nowres = a[i], p = i;
		while (p <= n)
		{
			int l = p + 1, r = n, rr = 0;
			while (l <= r)
			{
				int mid = l + r >> 1;
				int gc = query(i, mid);
				if (gc >= nowres)
				{
					l = mid + 1;
				}
				else
				{
					r = mid - 1;
					rr = mid;
				}
			}
			if (rr == 0) break;
			nowres = query(i, rr);
			p = rr - 1;
			if (p - i + 1 >= k)
			{
				ans = max(ans, (sum[p] - sum[i - 1]) * (long long)(query(i, rr - 1)));
				//printf("%d %d\n", i, p);
			}
			p = rr;
		}
		ans = max(ans, (sum[n] - sum[i - 1]) * query(i, n));
	}
	printf("%lld\n", ans);
	return 0;
}
posted @   HappyBobb  阅读(6)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示