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