提交: 57 解决: 19
[ 提交][ 状态][ 讨论版][命题人: admin]
题目描述
给定一个长为n的正整数序列Ai。对于它的任意一个连续的子序列{Al, Al+1, ..., Ar},
定义其权值W (l, r)为其长度与序列中所有元素的最大公约数的乘积,即W (l, r) = (r − l + 1) × gcd(Al, Al+1, .., Ar )。
你需要输出权值最大的子序列的权值
你需要输出权值最大的子序列的权值
输入
第一行一个正整数n。
第二行n个正整数,表示序列Ai。
第二行n个正整数,表示序列Ai。
输出
一行一个正整数,表示答案。
样例输入
5
30 60 20 20 20
样例输出
80
提示
最后四个元素形成的子序列权值最大。
对于前30%的数据:n ≤ 2000
对于所有数据:1 ≤ n ≤ 105,1 ≤ Ai ≤ 109
来源
【思路】
有一个定理 : 长度为n的子序列中 , GCD 最多为log(n)
在 BZOJ 上 这个 时间限度时 10s 在 upc 上 限定1s ;
很尬尬的用 Map 数组, 在bzoj上跑1s 在 upc 上 跑1092ms 差一丢丢 就是过不去;
改用数组标记 时间 降到128ms , 说明UPC 对 STL 库 的支持 不是很好哇;
固定右端点(枚举右端点) 去掉重复的 gcd , 延伸最左端点能达到最长;
map 的话 不断翻滚, 数组 是去重
【代码实现】
STL map的‘
#include <iostream>
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const ll INF=0x3f3f3f3f;
const int MAXN=1e5+5;
const int MOD=1e9+7;
using namespace std;
inline ll gcd(ll a,ll b) { return b? gcd(b,a%b):a;}
ll a[MAXN];
map<ll,ll>mp,tmp;
map<ll,ll>::iterator it;
int main()
{
int n;
ll ans=-INF;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
ans=max(ans,a[i]);
for(it=mp.begin();it!=mp.end();it++)
{
ll now_gcd = gcd(it->first,a[i]);
ans= max(ans, now_gcd*(i-it->second+1));
if(!tmp[now_gcd])
tmp[now_gcd]=(it->second);
else
tmp[now_gcd]= min(tmp[now_gcd],it->second); // 取left最远
}
if(!tmp[a[i]])
tmp[a[i]]=i;
mp=tmp;
tmp.clear();
}
printf("%lld",ans);
return 0;
}
用数组标记的 128ms
#include <iostream>
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const ll INF=0x3f3f3f3f;
const int MAXN=1e5+5;
const int MOD=1e9+7;
using namespace std;
inline ll gcd(ll a,ll b) { return b? gcd(b,a%b):a;}
ll col[MAXN];
ll gc[MAXN];
ll a[MAXN];
map<ll,ll>mp,tmp;
map<ll,ll>::iterator it;
int main()
{
int n;
ll ans=-INF;
int k=0,cot;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
col[++k]=i;
gc[k]=a[i];
for(int j=k-1;j>=1;j--)
gc[j]=gcd(gc[j],gc[j+1]);
int cot=0;
for(int j=1;j<=k;)
{
gc[++cot]=gc[j];
col[cot]=col[j];
while(gc[cot]==gc[j]) j++;
}
k=cot;
for(int j=1;j<=k;j++)
{
ans=max(ans,gc[j]*(i-col[j]+1));
}
}
printf("%lld",ans);
return 0;
}
123