紫书上的数论经典题。题意大概是这样的,给一段正整数序列,问gcd(a i,a i+1,…,a j)*(j-i+1)的最大值。
其实不能,就是右端点从前往右扫,遍历整个区间,左端点从右端点往左扫,直到起点。数据维护每个gcd,index.
反正核心就是相同gcd的删掉,时间复杂度大概就是nlong(ai)
/************************************************
┆ ┏┓ ┏┓ ┆
┆┏┛┻━━━┛┻┓ ┆
┆┃ ┃ ┆
┆┃ ━ ┃ ┆
┆┃ ┳┛ ┗┳ ┃ ┆
┆┃ ┃ ┆
┆┃ ┻ ┃ ┆
┆┗━┓ ┏━┛ ┆
┆ ┃ ┃ ┆
┆ ┃ ┗━━━┓ ┆
┆ ┃ AC代马 ┣┓┆
┆ ┃ ┏┛┆
┆ ┗┓┓┏━┳┓┏┛ ┆
┆ ┃┫┫ ┃┫┫ ┆
┆ ┗┻┛ ┗┻┛ ┆
************************************************ */
#pragma warning (disable:4996)
#include<iostream>
#include<algorithm>
#include<string>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<set>
#include<list>
#include<map>
#include<stack>
#include<cstdlib>
#include<functional>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
const int maxn = 1e5 + 10;
struct node
{
ll gcd;
int index;
}a[maxn];
list<node> lt;
ll __gcd(ll aa,ll bb)
{
if(bb==0)
return aa;
return __gcd(bb,aa%bb);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i].gcd);
a[i].index=i;
}
lt.clear();
ll ans=0;
for(int i=1;i<=n;i++)
{
ans=max(a[i].gcd,ans);
ll &x=a[i].gcd;
for(list<node> :: iterator it=lt.begin(),that;it!=lt.end();it++)
{
it->gcd=__gcd(it->gcd,x);
that=it;
that++;
while(that!=lt.end())
{
that->gcd=__gcd(that->gcd,x);
if(that->gcd==it->gcd)
{
lt.erase(it);
it=that;
that++;
}
else
break;
}
ans=max(ans,(i - it->index + 1)*it->gcd);
}
lt.push_front(a[i]);
}
printf("%lld\n",ans);
}
return 0;
}