赞
踩
给定一个数组,每次操作可以选择数组中任意两个相邻的元素 x, y 并将其中的一个元素替换为 gcd(x, y) ,其中 gcd(x, y) 表示 x 和 y 的最大公约数。
请问最少需要多少次操作才能让整个数组只含 1 。
输入的第一行包含一个整数 n ,表示数组长度。
第二行包含 n 个整数 a1, a2, · · · , an,相邻两个整数之间用一个空格分隔。
输出一行包含一个整数,表示最少操作次数。如果无论怎么操作都无法满足要求,输出 −1 。
样例输入
3
4 6 9
4
对于 30% 的评测用例,n ≤ 500 ,ai ≤ 1000;
对于 50% 的评测用例,n ≤ 5000 ,ai ≤ 1 0 6 10^6 106;
对于所有评测用例,1 ≤ n ≤ 100000 ,1 ≤ ai ≤ 1 0 9 10^9 109。
性质 or 结论: g c d ( 1 , x ) = 1 gcd(1, x) = 1 gcd(1,x)=1
我们需要找最小次数去得到
1
1
1
有
1
1
1 之后顺着就可以把所有数变成
1
1
1
我们可以通过线段树 维护区间 GCD
然后通过二分求解最小次数
/* Make it simple and keep self stupid author:Joanh_Lan */ #pragma GCC optimize(3) #pragma GCC optimize("inline") // 如果比赛允许开编译器优化的话,可以默写这两段 #include <iostream> #include <algorithm> #include <vector> #include <string> #include <numeric> #include <cstring> #include <cmath> #include <map> #include <unordered_map> #include <bitset> #include <set> #include <random> #include <ctime> #include <queue> #include <stack> #include <climits> #define buff \ ios::sync_with_stdio(false); \ cin.tie(0); // #define int long long #define ll long long #define PII pair<int, int> #define px first #define py second typedef std::mt19937 Random_mt19937; Random_mt19937 rnd(time(0)); using namespace std; const int mod = 1e9 + 7; const int inf = 2147483647; const int N = 100009; //int Mod(int a,int mod){return (a%mod+mod)%mod;} //int lowbit(int x){return x&-x;}//最低位1及其后面的0构成的数值 //int qmi(int a, int k, int p){int res = 1 % p;while (k){if (k & 1) res = Mod(res * a , p);a = Mod(a * a , p);k >>= 1;}return res;} //int inv(int a,int mod){return qmi(a,mod-2,mod);} //int lcm(int a,int b){return a*b/__gcd(a,b);} int n, a[N], tr[N << 2]; void bulid(int l, int r, int p) { if (l == r) { tr[p] = a[l]; return; } int mid = l + (r - l >> 1); bulid(l, mid, p << 1); bulid(mid + 1, r, p << 1 | 1); tr[p] = __gcd(tr[p << 1], tr[p << 1 | 1]); } int query(int l, int r, int s, int t, int p) { int ans = 0; if (l >= s && r <= t) return tr[p]; int mid = l + (r - l >> 1); if (mid >= s) ans = __gcd(ans, query(l, mid, s, t, p << 1)); if (mid < t) ans = __gcd(ans, query(mid + 1, r, s, t, p << 1 | 1)); return ans; } void solve() { cin >> n; int cnt_one = 0; for (int i = 1; i <= n; i++) { cin >> a[i]; if (a[i] == 1) cnt_one++; } if (cnt_one) { cout << n - cnt_one << '\n'; return; } bulid(1, n, 1); int ans = inf; for (int i = 1; i <= n; i++) { int l = i, r = n; int cnt = inf; while (l <= r) { int mid = l + (r - l >> 1); if (query(1, n, i, mid, 1) == 1) cnt = mid - i, r = mid - 1; else l = mid + 1; } ans = min(ans, cnt); } // cout << ans << '\n'; if (ans == inf) { cout << -1 << '\n'; return; } ans = ans + n - 1; cout << ans << '\n'; } int main() { buff; int _ = 1; // cin >> _; while (_--) solve(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。