【CodeForces - 892C 】Pride (数学,思维构造,gcd)

版权声明:欢迎学习我的博客,希望ACM的发展越来越好~ https://blog.csdn.net/qq_41289920/article/details/84641446

题干:

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 ≤ 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.

题目大意:

   给你一组数,定义一个操作:每次可以选择相邻的两个并且把其中一个的值变成他俩的gcd,,求问多少次操作后可以把这组数变成全1的、

给你一个长度为n的数组a。每次操作你可以选择相邻的两个位置a[i],a[i+1],将其中某一个数用gcd(a[i],a[i+1])来代替。
你的目标是最后将a中所有元素都变成1,问最少需要多少次操作。如果无论怎样最后a数组不能全变成1,那么输出-1

解题报告:

  看数据量,o(n^2)暴力就好了。。首先凑出一个1,然后剩下的次数就是剩下不是1的个数了。。

   这样构造的正确性想想就出来了。。其实也不难想,,因为你每次操作最多就改变一个数嘛、、假设就算这些数全是互质的,那也就是相当于先挑任意俩个来凑出个1,然后再去更新其他值嘛,,所以和直接看1的个数是一样的,,所以这题的关键点在于找1,而不是找互质的两个数。

贴一个题解:当序列中有1时,则gcd(1,s[i])最优。如果没有1,要凑出一个1. 
gcd(gcd(a,b),gcd(b,c))=gcd(gcd(a,b),c)=gcd(a,gcd(b,c))

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
const int INF = 0x3f3f3f3f;
int a[MAX];
int main()
{
	int t,cnt=0,n;
	int minn = INF;
	cin>>n;
	for(int i = 1; i<=n; i++) {
		scanf("%d",a+i);
		if(a[i] == 1) cnt++;
	}
	if(cnt!=0) {
		printf("%d\n",n-cnt);return 0 ;
	}
	int g;
	for(int i = 1; i<n; i++) {
		g=a[i];
		for(int j = i+1; j<=n; j++) {
			g=__gcd(g,a[j]);
			if(g==1) {
				minn = min(minn,j-i+n-1);//相当于先凑出这个1用了j-i,然后相当于cnt=1的上面那种情况,用n-cnt步来凑出答案。
				break;
			}
		}
	}
	if(minn == INF) puts("-1");
	else printf("%d\n",minn);
	return 0 ;
 }

猜你喜欢

转载自blog.csdn.net/qq_41289920/article/details/84641446