首页 > 学院 > 开发设计 > 正文

C - Magical GCD UVALive - 6582

2019-11-08 01:55:24
字体:
来源:转载
供稿:网友

题意:就是找个连续子序列,使得长度乘上这个子序列的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;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表