|
|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 zhangjinxuan 于 2023-6-6 11:45 编辑
【重金悬赏】是吸引你点进来的,但是真的有重金悬赏。
这个题想了亿天了,决定来问亿问。
题目描述
给定一个长度为 n 的正整数序列 a,请找到两个数 l, r,使 gcd(al, al+1, ..., ar) + al, al+1, ..., ar 最大,输出 l, r,并且输出这个最大值。
gcd 表示最大公因数。
例如:
输出:
解释:gcd(8, 16, 24) + 8 + 16 + 24 = 56,这是最大的。
数据范围:
1 <= n <= 1000000
a 的所有元素都大于等于 1,小于等于 1000000。
想了很久也没有什么头绪,望高人赐教。
@陈尚涵 @额外减小 @tommyyu
成功解决者,额外赏 30 鱼币。
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 1e6 + 5;
int a[MAXN];
ll pre[MAXN]; // 前缀和
int gcd(int a, int b) {
while (b) a %= b, swap(a, b);
return a;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
pre[i] = pre[i - 1] + a[i];
}
ll best = -1;
int ansL = 1, ansR = 1;
vector<pair<int, int>> cur; // (gcd, l)
for (int r = 1; r <= n; ++r) {
vector<pair<int, int>> tmp;
tmp.emplace_back(a[r], r);
// 合并前面的 GCD
for (auto &p : cur) {
int g = p.first;
int l = p.second;
int new_g = gcd(g, a[r]);
if (!tmp.empty() && tmp.back().first == new_g) continue;
tmp.emplace_back(new_g, l);
}
// 更新最优答案
for (auto &p : tmp) {
int g = p.first;
int l = p.second;
ll sum = pre[r] - pre[l - 1];
ll now = sum + g;
if (now > best) {
best = now;
ansL = l;
ansR = r;
}
}
cur.swap(tmp);
}
cout << ansL << " " << ansR << "\n";
cout << best << "\n";
return 0;
}
|
|