P1024 [NOIP 2001 提高组] 一元三次方程求解
题目描述
有形如:$ a x^3 + b x^2 + c x + d = 0 $ 这样的一个一元三次方程。给出该方程中各项的系数($ a,b,c,d $ 均为实数),并约定该方程存在三个不同实根(根的范围在 $ -100 $ 至 $ 100 $ 之间),且根与根之差的绝对值 $ \ge 1 $。要求由小到大依次在同一行输出这三个实根(根与根之间留有空格),并精确到小数点后 $ 2 $ 位。
提示:记方程 $ f(x) = 0 $,若存在 $ 2 $ 个数 $ x_1 $ 和 $ x_2 $,且 $ x_1 < x_2 , , , f(x_1) \times f(x_2) < 0 $,则在 $ (x_1, x_2) $ 之间一定有一个根。
输入格式
一行,$ 4 $ 个实数 $ a, b, c, d $。
输出格式
一行,$ 3 $ 个实根,从小到大输出,并精确到小数点后 $ 2 $ 位。
输入输出样例 #1
输入 #1
1 -5 -4 20
输出 #1
-2.00 2.00 5.00
说明/提示
【题目来源】
NOIP 2001 提高组第一题
题解:
就是特别要注意输入不是整数实数,所以用double,然后就是数学的零点存在定理,再运用二分法求出零点所在
#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
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;
for (double x = -100; x <= 100; x++) {
double left = x, right = x + 1;
if (f(left) * f(right) == 0) {
if (f(left) == 0) {
printf("%.2f ", left);
}
}
else if (f(left) * f(right) < 0) {
while (right - left >=0.001) {
double mid = right + (left - right) / 2;
if (f(left) * f(mid) < 0) {
right = mid;
}
else {
left = mid;
}
}
printf("%.2f ", left);
}
else continue;
}
return 0;
}
P1182 数列分段 Section II
题目描述
对于给定的一个长度为 $ N $ 的正整数数列 $ A_{1\sim N} $,现要将其分成 $ M ( ( ( M\leq N $)段,并要求每段连续,且每段和的最大值最小。
关于最大值最小:
例如一数列 $ 4\ 2\ 4\ 5\ 1 $ 要分成 $ 3 $ 段。
将其如下分段:
$ [4\ 2][4\ 5][1] $
第一段和为 $ 6 $,第 $ 2 $ 段和为 $ 9 $,第 $ 3 $ 段和为 $ 1 $,和最大值为 $ 9 $。
将其如下分段:
$ [4][2\ 4][5\ 1] $
第一段和为 $ 4 $,第 $ 2 $ 段和为 $ 6 $,第 $ 3 $ 段和为 $ 6 $,和最大值为 $ 6 $。
并且无论如何分段,最大值不会小于 $ 6 $。
所以可以得到要将数列 $ 4\ 2\ 4\ 5\ 1 $ 要分成 $ 3 $ 段,每段和的最大值最小为 $ 6 $。
输入格式
第 $ 1 $ 行包含两个正整数 $ N,M $。
第 $ 2 $ 行包含 $ N $ 个空格隔开的非负整数 $ A_i $,含义如题目所述。
输出格式
一个正整数,即每段和最大值最小为多少。
输入输出样例 #1
输入 #1
5 3
4 2 4 5 1
输出 #1
6
说明/提示
对于 $ 20% $ 的数据,$ N\leq 10 $。
对于 $ 40% $ 的数据,$ N\leq 1000 $。
对于 $ 100% $ 的数据,$ 1\leq N\leq 10^5 , , , M\leq N , , , A_i < 10^8 $, 答案不超过 $ 10^9 $。
解题思路:就是输入的时候找到数组中最大值还有数组的和,然后进行一下二分,如果为数组最大值,遍历一遍,看是否刚刚能够构成最大值最小的组合
#include<bits/stdc++.h>
using namespace std;
int n, m, r, l,a[100001];
bool isTrue(int x) {
int num = 0, total = 0;
for (int i = 1; i <= n; i++) {
if (total + a[i] <= x)total += a[i];
else
{
total = a[i];
num++;
}
}
return num < m;
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> a[i];
l = max(l, a[i]);
r += a[i];
}
while (l <= r) {
int mid = (l + r) / 2;
if (isTrue(mid))r = mid - 1;
else l = mid+1;
}
cout << l;
return 0;
}