CF892C (gcd++)
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
Copy
5 2 2 3 4 6output
Copy
5input
Copy
4 2 4 6 8output
Copy
-1input
Copy
3 2 6 9output
Copy
4Note
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.
題意:大體的意思就是給你一串數,可以進行的操作是把兩個相鄰數的任意一個替換成他們的最大公約數,問你最少需要多少次操作才能把這一串數都變成1
思路:其實想想不難,如果這一串數中有一個1,那麼用這個1去和他相鄰的數做gcd,總共需要做n-1次就可以完成。
以此類推,如果有m個1,就需要n-m次操作。
那如果原來的序列中沒有1呢?
那就只能用到列舉,列舉所有可能出現的情況來尋找把其中一個數變為1的最少的操作次數,剩下的就用上邊的結論就可以了。
AC程式碼;
#include<iostream>
#include<cstdio>
#define inf 0x3f3f3f
using namespace std;
int a[2005];
int gcd(int a,int b)
{
return b?gcd(b,a%b):a;
}
int main()
{
int n,i,j;
int cnt=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==1) cnt++;
}
if(cnt)
{
cout<<n-cnt<<endl;
return 0;
}
int index=0;
int flag=0;
int minn=inf;
for(i=1;i<=n;i++)
{
int x=a[i];
for(j=i+1;j<=n;j++)
{
x=gcd(x,a[j]);
if(x==1)
{
index=j-i;
minn=min(minn,index);
flag=1;
break;
}
}
}
if(flag)
cout<<n-1+minn<<endl;
else cout<<"-1"<<endl;
return 0;
}