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;
}