4488: [Jsoi2015]最大公约数

4488: [Jsoi2015]最大公约数

Time Limit: 10 Sec   Memory Limit: 256 MB
Submit: 264   Solved: 152
[ Submit][ Status][ Discuss]

Description

给定一个长度为 N 的正整数序列Ai对于其任意一个连续的子序列
{Al,Al+1...Ar},我们定义其权值W(L,R )为其长度与序列中所有元素的最大公约数的乘积,即W(L,R) = (R-L+1) ∗ gcd (Al..Ar)。 
JYY 希望找出权值最大的子序列。

Input

输入一行包含一个正整数 N。
接下来一行,包含 N个正整数,表示序列Ai
1 < =  Ai < =  10^12, 1 < =  N < =  100,000

Output

输出文件包含一行一个正整数,表示权值最大的子序列的权值。

Sample Input

5
30 60 20 20 20

Sample Output

80
//最佳子序列为最后 4 个元素组成的子序列。

【分析】

有一个知识点:长度n的序列的所有子序列的公约数,最多有logn个。

枚举右端点,那么右端点之前的公约数个数最多logn个。维护这些公约数,每个出现的最左坐标(L)。

扫描所有公约数,取最优解。

【代码】

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,a[N];
int dex[N],g[N];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int top=0;
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        dex[++top]=i;
        g[top]=a[i];
        for(int k=top-1;k>=1;k--)
        {
            g[k]=__gcd(g[k],g[k+1]);
        }
        int j=0;
        for(int k=1;k<=top;)
        {
            g[++j]=g[k];
            dex[j]=dex[k];
            while(g[j]==g[k])k++;
        }
        top=j;
        for(j=1;j<=top;j++)
            ans=max(ans,1ll*g[j]*(i-dex[j]+1));
    }
    cout<<ans<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

雪的期许

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值