91 lines
3.3 KiB
C++
91 lines
3.3 KiB
C++
#include <iostream>
|
|
#include <vector>
|
|
#include <algorithm>
|
|
#include <numeric>
|
|
|
|
using namespace std;
|
|
|
|
void log_vector(const vector<int>& vec, const string& prefix = "") {
|
|
clog << prefix;
|
|
for (const int i : vec) { clog << i << " "; }
|
|
clog << endl;
|
|
}
|
|
|
|
vector<int> get_divisors(const int n) {
|
|
vector<int> small_divisors = {1};
|
|
vector<int> big_factors = {n};
|
|
for (int i = 2; i * i <= n; i++) {
|
|
if (n % i == 0) {
|
|
small_divisors.push_back(i);
|
|
big_factors.push_back(n / i);
|
|
}
|
|
}
|
|
// reverse(small_divisors.begin(), small_divisors.end());
|
|
// big_factors.insert(big_factors.end(), small_divisors.begin(), small_divisors.end());
|
|
// return big_factors;
|
|
reverse(big_factors.begin(), big_factors.end());
|
|
small_divisors.insert(small_divisors.end(), big_factors.begin(), big_factors.end());
|
|
return small_divisors;
|
|
}
|
|
|
|
/// 需要保证 sorted_cut_sticks 有序;需要保证 target_length 是总长度的因数
|
|
bool verify_length_greedy(vector<int> sorted_cut_sticks, const int target_length) {
|
|
// if (target_times == 0) { return true; }
|
|
// if (sorted_cut_sticks.empty()) { throw logic_error("Invalid target_times"); }
|
|
if (sorted_cut_sticks.empty()) { return true; }
|
|
if (sorted_cut_sticks.back() > target_length) { return false; }
|
|
int remaining_length = target_length - sorted_cut_sticks.back();
|
|
sorted_cut_sticks.pop_back();
|
|
if (remaining_length == 0) {
|
|
return verify_length_greedy(sorted_cut_sticks, target_length);
|
|
}
|
|
while (true) {
|
|
auto closest_iter = lower_bound(sorted_cut_sticks.begin(), sorted_cut_sticks.end(), remaining_length);
|
|
if (closest_iter != sorted_cut_sticks.end() && *closest_iter == remaining_length) {
|
|
sorted_cut_sticks.erase(closest_iter);
|
|
// log_vector(sorted_cut_sticks, "after erase: ");
|
|
return verify_length_greedy(sorted_cut_sticks, target_length);
|
|
}
|
|
if (closest_iter == sorted_cut_sticks.begin()) { // 都太长了!
|
|
return false;
|
|
}
|
|
closest_iter -= 1; // 第一个小于 remaining_length 的元素的 iter
|
|
remaining_length -= *closest_iter;
|
|
sorted_cut_sticks.erase(closest_iter);
|
|
}
|
|
}
|
|
|
|
int get_shortest_original_length(vector<int> cut_sticks) {
|
|
sort(cut_sticks.begin(), cut_sticks.end());
|
|
const int total_length = accumulate(cut_sticks.begin(), cut_sticks.end(), 0);
|
|
const vector<int> divisors = get_divisors(total_length);
|
|
log_vector(divisors, "divisors: ");
|
|
for (const int divisor : divisors) {
|
|
if (verify_length_greedy(cut_sticks, divisor)) {
|
|
return divisor;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int main() {
|
|
ios::sync_with_stdio(false);
|
|
cin.tie(nullptr);
|
|
|
|
int cut_sticks_amount;
|
|
while (cin >> cut_sticks_amount && cut_sticks_amount) {
|
|
vector<int> cut_sticks(cut_sticks_amount);
|
|
for (int i = 0; i < cut_sticks_amount; i++) {
|
|
cin >> cut_sticks[i];
|
|
}
|
|
sort(cut_sticks.begin(), cut_sticks.end());
|
|
log_vector(cut_sticks, "cut_sticks: ");
|
|
// int target_length;
|
|
// cin >> target_length;
|
|
// cout << (verify_length_greedy(cut_sticks, target_length) ? "Yes" : "No") << endl;
|
|
cout << get_shortest_original_length(cut_sticks) << endl;
|
|
}
|
|
|
|
return 0;
|
|
}
|