题意:给出一个长度在 100000 以内的正整数序列,大小不超过 10^12。 求一个连续子序列,使得在所有的连续子序列中,它们的GCD值乘以它们的长度最大。
这个题我真的naive了,写了一个分治的做法后调了半天还是WA,后来怒查题解...
枚举终点j,则[i,j]中的gcd最多有log(n)种
用一个数组(其实本来就是单调的)存下来,每次把栈中元素都与a[j]做gcd,把a[j]放到后面
然后gcd值相同的合并,然后就没有然后了...
这个题的做法也可以拓展到一些其他题上,比如位运算等
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
using namespace std;
int n;
long long a[M],ans;
pair<int,long long> stack[20],_stack[20];
int top;
void Initialize()
{
ans=0;
top=0;
}
int main()
{
// freopen("in.txt","r",stdin);
// freopen("std.txt","w",stdout);
int T,i,j;
for(cin>>T;T;T--)
{
Initialize();
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
stack[++top]=make_pair(i,0);
for(j=1;j<=top;j++)
stack[j].second=__gcd(stack[j].second,a[i]);
int temp=0;
for(j=1;j<=top;j++)
if(j==1||stack[j].second!=stack[j-1].second)
_stack[++temp]=stack[j];
memcpy(stack,_stack,sizeof stack);
top=temp;
for(j=1;j<=top;j++)
ans=max(ans,stack[j].second*(i-stack[j].first+1));
}
printf("%lld\n",ans);
}
return 0;
}