一.算法题总结
1.
解题思路:对于这个题,我最开始想到就是二分,但是头痛的是有三个解,如果我在-100到100之间二分,那么只能得出一个解,然后我就想了一下,这个要求精度,那么0.01这么小,好像可以在0-1之间或者-1-1之间二分,然后我就觉得好像可以遍历这俩百个格子,每个格子长度为一,进行二分求解
#include <iostream>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;
double a, b, c, d;
double f(double x) {
return a * x * x * x + b * x * x + c * x + d;
}
int main() {
cin >> a >> b >> c >> d;
int ans = 0;
for (int i = -100; i < 100; i++) {
if (ans == 3)break;
double l = i;
double r = i + 1;
double f1 = f(l);
double f2 = f(r);
if (f1 == 0) {
ans++;
printf("%.2f ", l);
continue;
}
if (f1 * f2 < 0) {
while (r - l >= 0.001) {
double mid = (l + r) / 2;
if (f(mid) * f(l) <= 0)
r = mid;
else
l = mid;
}
printf("%.2f ", l);
ans++;
}
}
return 0;
}
2.
解题思路:对于这个题,我写过Section I,所以就看出了要用贪心, 但在这个贪心要怎么用呢,也没给我个具体的数,让区间的和小于某个数,这个时候,我想起了二分,用二分来猜数的大小,而这个数的大小,就是看这个区间的是否大于它,这就可以贪心了
#include <iostream>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;
bool isPossible(int mid, const vector<int>& nums, int m) {
int count = 1;
int current_sum = 0;
for (int num : nums) {
if (current_sum + num <= mid) {
current_sum += num;
}
else {
current_sum = num;
count++;
if (count > m) {
return false;
}
}
}
return true;
}
int main() {
int n, m;
cin >> n >> m;
vector<int> nums(n);
int max_num = 0;
int total_sum = 0;
for (int i = 0; i < n; ++i) {
cin >> nums[i];
max_num = max(max_num, nums[i]);
total_sum += nums[i];
}
int left = max_num;
int right = total_sum;
int answer = total_sum;
while (left <= right) {
int mid = left + (right - left) / 2;
if (isPossible(mid, nums, m)) {
answer = mid;
right = mid - 1;
}
else {
left = mid + 1;
}
}
cout << answer << endl;
return 0;
}
3.
解题思路:今天写的最难的一个题,其实怪自己眼挫,没注意到(尽可能让前面的人少抄),其实这个题的本质也是贪心+二分,我就是这么写的,思路和上面的题一样,但是一直只能过4个,然后看了一下别人的题解,发现漏了个条件(尽可能让前面的人少抄),有了这个以后,那就反过来在对答案抄一边就行了
#include <iostream>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;
int m, k;
struct lr {
ll l, r;
};
vector<lr> len;
bool check(ll x, vector<ll>& nums) {
ll sum = 0;
int cnt = 1;
vector<lr> temp;
lr current; current.l = 1;
for (int i = 1; i <= m; i++) {
if (nums[i] > x) return false;
if (sum + nums[i] <= x) {
sum += nums[i];
} else {
current.r = i - 1;
temp.push_back(current);
cnt++;
sum = nums[i];
current.l = i;
}
if (cnt > k) return false;
}
current.r = m;
temp.push_back(current);
if (cnt == k) {
len = temp;
return true;
}
return cnt<=k;
}
void check2(ll x, vector<ll>& nums) {
ll sum = 0;
int cnt = 1;
vector<lr> temp;
lr current; current.r = m;
for (int i = m; i >= 1; i--) {
if (sum + nums[i] <= x) {
sum += nums[i];
} else {
current.l = i + 1;
temp.push_back(current);
cnt++;
sum = nums[i];
current.r = i;
}
}
current.l = 1;
temp.push_back(current);
reverse(temp.begin(), temp.end());
len = temp;
}
int main() {
cin >> m >> k;
vector<ll> nums(m + 1);
ll left = 0, right = 0;
for (int i = 1; i <= m; i++) {
cin >> nums[i];
right += nums[i];
if (nums[i] > left) left = nums[i];
}
ll ans = right;
while (left <= right) {
ll mid = (left + right) / 2;
if (check(mid, nums)) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
// 确保前面的人尽可能少抄写
check2(ans, nums);
for (int i = 0; i < k; i++) {
cout << len[i].l << " " << len[i].r << endl;
}
return 0;
}