C - Magical GCD UVALive - 6582

C - Magical GCD UVALive - 6582_第1张图片

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

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

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

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

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

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

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

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

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

#include 
using namespace std;
typedef long long ll;
ll a[100005];
mapv;
map::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<







你可能感兴趣的:(思维)