codeforces A.pride 数学题 gcd

时间:2021-08-29 05:18:38

题目大意:给你一个序列,每次可以选两个相邻的数,取最大公约数,然后将最大公约数替换其中一个数。问最少操作几次可以将所有数都变为1。

思路:要求最少操作,只需要求出最短的公共的gcd为一的区间的长度,几个例子,如果有a,b,c,d,e,f,g这7个数,

第一轮可以枚举gcd(a,b),gcd(b,c),gcd(c,d),gcd(d,e),gcd(e,f),gcd(f,g),

第二轮可以枚举gcd(a,b,c),gcd(b,c,d),gcd(c,d,e),gcd(d,e,f),gcd(e,f,g),

第三轮可以枚举gcd(a,b,c,d),gcd(b,c,d,e),gcd(c,d,e,f),gcd(d,e,f,g),

第四轮可以枚举gcd(a,b,c,d,e),gcd(b,c,d,e,f),gcd(c,d,e,f,g),

第五轮可以枚举gcd(a,b,c,d,e,f),gcd(b,c,d,e,f,g),

第六轮可以枚举gcd(a,b,c,d,e,f,g),

顺序执行每一轮,如果其中某一轮中gcd为1,则总操作数为n+轮数-1。

如果数组中原先有1,则另外考虑。

#include<cstdio>
#include<cstring>
#include<iostream>
#define maxn 2005
#define LL long long
#define mod 1000000007
using namespace std;
LL gcd(LL a,LL b)
{
	if(b==0)
		return a;
	return gcd(b,a%b);
}
int main()
{
	ios::sync_with_stdio(false);
	int n;
	int a[maxn];
	while(cin>>n)
	{
		int sum=0;
		for(int i=0;i<n;i++)
		{
			cin>>a[i];
			if(a[i]==1)
				sum++;
		}
		int cur;
		cur=a[0];
		for(int i=1;i<n;i++)
		{
			cur=gcd(cur,a[i]);
		}
		if(cur!=1)
		{
			cout << -1 << endl;
			continue;
		}
		if(sum!=0)
		{
			cout << n-sum << endl;
			continue;
		}
		int flag,ans;
		flag=0;
		for(int i=1;i<n;i++)
		{
			for(int j=0;j<n-i;j++)
			{
				a[j]=gcd(a[j],a[j+1]);
				if(a[j]==1)
				{
					ans=n+i-1;
					flag=1;
					break;
				}
			}
			if(flag)
				break;
		}
		cout << ans << endl;
	}	
	return 0;	
}