然后,你必须使数组中的所有元素相等。一开始,你选择一个==正整数==x(x\>0 )在一次操作中,你将 x 恰好加到数组的一个元素上。
==注意,所有操作中 x 都是相同的==。
在你选择 a[n+1]和 x 之后,使所有元素相等的最小操作次数是多少?
解题思路
假设数组a 中有元素x, y, z (三者互不相等, 其中 z 最大) , 那么我们就需要找到一个数w,使得 x+k1*w=z, y+k2*w=z
显然就可以看出一个性质w=gcd(abs(x-y), abs(y-z))
就这样我们找到了题目中的x,接下来, 我们需要找插入的a[n+1]
令 ma=max(a),因为元素互不相等, 我们就需要找插入比ma大k*w 和比ma小k*w的两个数,
分别重新找出最大值, 并计算所有元素加到ma的次数
输出两种情况下最小的次数.
代码
cpp
#include<bits/stdc++.h>
#define int long long #define endl '\n' constint INF = 0x3f3f3f3f;
voidsolve(){ int n; std::cin >> n; std::vector<int> a, b; std::map<int , int> mp; for(int i = 0 ; i < n ; i ++){ int x; std::cin >> x,a.push_back(x), b.push_back(x), mp[a[i]] = 1; }
int w = unique(a.begin (), a.end()) - a.begin (); if(w == 1){ std::cout << 1 << endl; return ; } int o = abs(a[1] - a[0]); for(int i = 2 ; i < n ; i ++) o = std::__gcd(abs(a[i] - a[i - 1]), o); // std::cout << o << endl; int cnt = 0; int k1 = *std::max_element (a.begin (), a.end ()); while(true){ cnt ++; if(mp[k1 - cnt * o] != 1){ a.push_back (k1 - cnt * o); break; } } k1 = *std::max_element (a.begin (), a.end ()); int ans1 = 0, ans2 = 0; for(int i = 0 ; i < (int)a.size(); i ++) ans1 += abs(a[i] - k1) / o; cnt = 0; int k2 = *std::max_element (b.begin (), b.end ()); while(true){ cnt ++; if(mp[k2 + cnt * o] != 1){ b.push_back (k2 + cnt * o); break; } } k2 = *std::max_element (b.begin (), b.end ()); for(int i = 0 ; i < (int)b.size(); i ++) ans2 += abs(a[i] - k2) / o; std::cout << std::min(ans1, ans2) << endl;
}
signedmain(){ std::ios::sync_with_stdio (false); std::cin.tie (nullptr), std::cout.tie (nullptr); int Lazy_boy_ = 1; std::cin >> Lazy_boy_; while (Lazy_boy_--) solve (); return0; }