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