大体题意:
给你n 个整数(n <= 1e5)要求选择一个连续的子序列,使得gcd * 长度 最大?
思路:
按照刘汝佳分析做的,加入一个数后,给它的所有后缀的gcd 打一个表,gcd 相同的 保留长度大的,其余的全部删除。
那么这个表中元素数量最大是log2 j 个,很小的一个数。
因此随便做了,但是不能用有序的stl 如set 还是会超时。
用两个Hash map 来会导就可以了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
#include <unordered_map>
#define Max(a,b) ((a)>(b)?(a):(b))
#define ps push_back
#define fi first
#define se second
#define Siz(x) (int)x.size()
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
LL gcd(LL a,LL b){
return !b ? a : gcd(b,a%b);
}
LL a[maxn];
LL b[maxn];
unordered_map <LL,int>mp,mp2;
unordered_map<LL,int>::iterator it;
int T, n;
int main(){
scanf("%d",&T);
while(T--){
LL ans = 0;
mp.clear();
scanf("%d",&n);
for (int i = 1; i <= n; ++i){
scanf("%lld",a+i);
ans = Max(ans,a[i]);
}
mp[a[1] ] = 1;
for (int i = 2; i <= n; ++i){
int cnt = 0;
mp2.clear();
for (it = mp.begin(); it != mp.end();++it){
LL ng = gcd(it->fi, a[i]);
LL nlen = it->se + 1;
if (!mp2.count(ng)){
mp2[ng] = nlen;
ans = Max(ans,nlen*ng);
}
else {
if (mp2[ng] < nlen){
mp2[ng] = nlen;
ans = Max(ans,nlen*ng);
}
else ans = Max(ans,mp2[ng]*ng);
}
}
if (!mp2.count(a[i]))mp2[a[i] ] = 1;
mp = mp2;
}
printf("%lld\n",ans);
}
return 0;
}
/**
2
5
30 60 20 20 20
4
2 2 3 4
ans = 80
**/