C - Magical GCD UVALive - 6582

本文介绍了一种寻找连续子序列中长度与GCD值乘积最大的算法优化方案。通过记录每个可能的GCD值及其对应的最长序列起始位置,实现对序列的高效遍历与更新。


题意:就是找个连续子序列,使得长度乘上这个子序列的gcd的值最大。

思路:嗯,比较容易想到的就是暴力,每次就是和前一个、前两个.....求gcd乘上长度。

好想的一个优化就是gcd相同的,我们只保留最长的那个序列就可以了。

我们保存[i,j-1]的gcd的数值。以及i这个位置

然后和j去求一个gcd。如果gcd没变。那么这个序列的值不变,最左边还是i,gcd也不变。

如果gcd变小了,那么当前这个序列就要改变,gcd的值改变,i的位置取之前最靠前的一个值。

这样我们每次保存一个最小的i就可以了。

很重要的一点就是随着数量的增加gcd是不断减小的。

然后不断的更新答案就可以了。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[100005];
map<ll,ll>v;
map<ll,ll>::iterator it,itt;
ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}
int main()
{
    int T,n;
    scanf("%d",&T);
    while (T--)
    {
        ll ans=0;
        scanf("%d",&n);
        v.clear();
        for (int i=1; i<=n; i++)
        {
            scanf("%lld",&a[i]);
            ans=max(ans,a[i]);
            for (it=v.begin(); it!=v.end(); it++)
            {
                if(gcd(it->first,a[i])!=it->first)//gcd的值变小了
                {
                    if (!v[gcd(it->first,a[i])])//如果之前没出现过
                        v[gcd(it->first,a[i])]=it->second;
                        cout<<v.size()<<endl;
                    //删除当前的值
                    itt=it++;
                    v.erase(itt);
                    it--;
                }
            }
            if (!v[a[i]])v[a[i]]=i;
            cout<<v.size()<<endl;
            for (auto it:v)
            {
                ans=max(ans,(it.first)*(i-it.second+1));
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值