题目链接:
892C Pride
大意:
给出一排数字,对这一排数字做一些操作如下:
每次对相邻的数字取 gcd,将结果赋给其中一个值。
求最少需要多少次操作 使得所有数字全为 1
思路:
先考虑有解的情况。
如果有 1,那么直接对应gcd下去就能出解。
那么如果没有1呢?
1 一定来自某两个上一级 gcd,上一级的 gcd 来自上上一级的 gcd
因此,只要暴力循环下去,求相邻的gcd,记录循环的次数,当出现 1 的时候,答案就是 n-1的个数+操作数
具体实现:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair <int,int> pii;
#define mem(s,t) memset(s,t,sizeof(s))
#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
#define pb push_back
//#define LOCAL
const int mod=1e9+7;
const int MAXN =2010;
int gcd(int a,int b) {return b?gcd(b,a%b):a;}
int n;
vector<int>a;
int main() {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
int x;
scanf("%d",&x);
a.pb(x);
}
if(n==1 && a[0]!=1){
puts("-1");
return 0;
}
int num=0,cnt=0;
int ok=0;
for(int i=0;i<a.size();i++){
if(a[i]==1){
ok++;
}
}
if(ok){
printf("%d\n",n+max(cnt-1,0)-ok);
return 0;
}
while(num<2010){
num++;
vector<int> ret;
if(a[0]==1){
printf("%d\n",n+max(0,cnt-1));
return 0;
}
for(int i=1;i<a.size();i++){
if(a[i]==1){
printf("%d\n",n+max(0,cnt-1));
return 0;
}
ret.pb(gcd(a[i],a[i-1]));
}
if(ret.size()==1 && ret[0]!=1){
puts("-1");
return 0;
}
cnt++;
a.clear();
for(int i=0;i<ret.size();i++){
a.pb(ret[i]);
}
}
return 0;
}