Codeforces 892 C. Pride (枚举)

Description

You have an array a with length n, you can perform operations. Each operation is like this: choose two adjacent elements from a, say x and y, and replace one of them with gcd(x, y), where gcd denotes the greatest common divisor.

What is the minimum number of operations you need to make all of the elements equal to 1?

 

Input

The first line of the input contains one integer n (1 ≤ n ≤ 2000) — the number of elements in the array.

The second line contains n space separated integers a1, a2, …, an (1 ≤ ai ≤ 10^9) — the elements of the array.

 

Output

Print -1, if it is impossible to turn all numbers to 1. Otherwise, print the minimum number of operations needed to make all numbers equal to 1.

 

Examples input

5
2 2 3 4 6

 

Examples output

5

 

题意

给定一个数列,我们定义一个操作是取相邻的两个数计算其 gcd ,然后替换掉其中的某一个数,问最少多少步可以将数列全部变为 1 。

 

思路

显然,数列所有数的 gcd 如果不等于 1 答案一定是 -1 。

对于其他情况,我们枚举找出最短的 gcd 为 1 的区间,此时的操作即,先造出一个 1 ,然后用这一个 1 与相邻的数字进行 gcd 填充。

注意特判 n = 1 的情况与数列中存在 1 的情况。

 

AC 代码

#include<bits/stdc++.h>
#define IO ios::sync_with_stdio(false);\
    cin.tie(0);\
    cout.tie(0);
using namespace std;
typedef __int64 LL;
const int maxn = 2e5+10;

LL a[maxn];
int n;
void solve()
{
    LL k = a[0],one = (a[0]==1);
    for(int i=1; i<n; i++)
    {
        k = __gcd(k,a[i]);
        if(a[i]==1)one++;
    }
    if(n==1&&a[0]==1)
    {
        cout<<0<<endl;
        return;
    }
    if(k!=1)
    {
        cout<<"-1"<<endl;
        return;
    }
    int lm = 0,ans = 3000;
    for(int i=0; i<n; i++)
    {
        LL k = a[i];
        for(int j=i+1; j<n; j++)
        {
            k = __gcd(k,a[j]);
            if(k==1)
            {
                lm = j-i+1;
                break;
            }
        }
        ans = min(ans,lm);
    }
    cout<<ans+n-2-one<<endl;
}

int main()
{
    IO;
    cin>>n;
    for(int i=0; i<n; i++)
        cin>>a[i];
    solve();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值