Codeforces 891A Pride (dp & 数学 & 贪心 & 暴力)

 

A. Pride

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You have an array a with length n, you can perform operations. Each operation is like this: choose two adjacent elements from a, say xand 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 ≤ 109) — 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

output

5

input

4
2 4 6 8

output

-1

input

3
2 6 9

output

4

Note

In the first sample you can turn all numbers to 1 using the following 5 moves:

  • [2, 2, 3, 4, 6].
  • [2, 1, 3, 4, 6]
  • [2, 1, 3, 1, 6]
  • [2, 1, 1, 1, 6]
  • [1, 1, 1, 1, 6]
  • [1, 1, 1, 1, 1]

We can prove that in this case it is not possible to make all numbers one using less than 5 moves.

题目链接:http://codeforces.com/problemset/problem/891/A

题意:有n个数,每次取两个相邻的数字x和y把其中的一个值x或者y改变成gcd(x,y),求把这所有的n个数都变成1的最少次数。

思路:很明显的一点是,如果这n个数中存在一个1的话,那么我们只需n-1次就可以把所有的n个数都变成1啦,所以这道题目就可以转变为求出使得n个数中至少存在一个1的最小步骤。

在求出gcd(x,y)时,把gcd(x,y)的值赋给y,因为这样总是可以更快的找出1(毕竟gcd()后的值已经少了一些因子,会使得两个数的gcd()变成1的可能性更大)。

分别以第1,2,.....i.....n-1个元素作为起始元素,直到第n个元素位置,并且求出使得n个数中出现1的最小的次数。

#include <bits/stdc++.h>
using namespace std;

int n,a[2100][2100],ans,num;

int gcd(int x, int y){
    return y ? gcd(y,x%y) : x;
}

int main(){
    scanf("%d",&n);
    for(int i = 0; i < n; i ++){
        scanf("%d",&a[i][i]);
        if(a[i][i] == 1) num ++;
    }
    if(num) printf("%d\n",n - num);
    else{
        ans = n+1;
        for(int i = 0; i < n; i ++){
            for(int j = i+1; j < n; j ++){
                a[i][j] = gcd(a[i][j-1],a[j][j]);
                if(a[i][j] == 1) ans = min(ans,j-i);
            }
        }
        if(ans == n+1) printf("-1\n");
        else printf("%d\n",ans+n-1);
    }
    return 0;
}

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值