二分三分

实数二分

例题 HDU-2199 Can you solve this equation?

题目链接

https://vjudge.net/problem/HDU-2199

题面

Description

Now,given the equation 8x^4 + 7x^3 + 2x^2 + 3x + 6 == Y,can you find its solution between 0 and 100;
Now please try your lucky.

Input

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has a real number Y (fabs(Y) <= 1e10);

Output

For each test case, you should just output one real number(accurate up to 4 decimal places),which is the solution of the equation,or “No solution!”,if there is no solution for the equation between 0 and 100.

Sample Input

2
100
-4

Sample Output

1.6152
No solution!

题解

这题就是最简单的实数二分,原方程是单调的,直接二分求解即可,重点是学习一下实数二分的写法,

AC代码

#include <bits/stdc++.h>
#define eps 1e-8//使用eps控制精度,越小循环次数也就越多
using namespace std;
double y;
double calc(double x) {
    return 8 * x * x * x * x + 7 * x * x * x + 2 * x * x + 3 * x + 6;
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%lf", &y);
        if (y < calc(0) || y > calc(100)) {
            printf("No solution!\n");
            continue;
        }
        double l = 0, r = 100;
        double mid;
        while (r - l > eps) {//循环条件注意是r-l>eps
            mid = (r + l) / 2;
            if (calc(mid) > y) r = mid;//注意这里是直接等于mid
            else l = mid;
        }
        printf("%.4f\n", mid);
    }
    return 0;
}

注意

当精度过高可能进入死循环风险时,可以通过一个变量控制循环次数,比如100次就停止

整数二分

例题 POJ-2785 4 Values whose Sum is 0

题目链接

https://vjudge.net/problem/POJ-2785

题面

Description

The SUM problem can be formulated as follows: given four lists A, B, C, D of integer values, compute how many quadruplet (a, b, c, d ) ∈ A x B x C x D are such that a + b + c + d = 0 . In the following, we assume that all lists have the same size n .

Input

The first line of the input file contains the size of the lists n (this value can be as large as 4000). We then have n lines containing four integer values (with absolute value as large as 2 28 ) that belong respectively to A, B, C and D .

Output

For each input file, your program has to write the number quadruplets whose sum is zero.

Sample Input

6
-45 22 42 -16
-41 -27 56 30
-36 53 -37 77
-36 30 -75 -46
26 -38 -10 62
-32 -54 -6 45

Sample Output

5

Hint

Sample Explanation: Indeed, the sum of the five following quadruplets is zero: (-45, -27, 42, 30), (26, 30, -10, -46), (-32, 22, 56, -46),(-32, 30, -75, 77), (-32, -54, 56, 30).

题解

简述一下题意,找到有多少对(a,b,c,d)满足a+b+c+d=0。

n为4000,\(n^3logn\)枚举前三个的和二分最后一个肯定会超时,那就预处理a+b的和,二分c+d的和即可,复杂度\(2n^2logn\)可以AC,预处理可以直接用一个multiset处理,\(upper\_bound-lower\_bound\)即为答案要加上的个数,因为如果没有正好相等的数upper_bound返回的地址刚好等于lower_bound

AC代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 4005
using namespace std;
int a[N], b[N], c[N], d[N];
int sum[N * N];
int main() {
    int n;
    while (scanf("%d", &n) != EOF) {
        for (int i = 1; i <= n; i++) {
            scanf("%d%d%d%d", &a[i], &b[i], &c[i], &d[i]);
        }
        int cnt = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                sum[++cnt] = a[i] + b[j];
            }
        }
        sort (sum + 1, sum + cnt + 1);
        long long ans = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                int x = -(c[i] + d[j]);
                ans += upper_bound(sum + 1, sum + cnt + 1, x) - lower_bound(sum + 1, sum + cnt + 1, x); 
            }
        }
        cout << ans << endl;
    }
    return 0;
}

二分答案

类型一:最大化最小值

例题 POJ-2456 Aggressive cows

题目链接

https://vjudge.net/problem/POJ-2456

题面

Description

Farmer John has built a new long barn, with N (2 <= N <= 100,000) stalls. The stalls are located along a straight line at positions x1,...,xN (0 <= xi <= 1,000,000,000).

His C (2 <= C <= N) cows don't like this barn layout and become aggressive towards each other once put into a stall. To prevent the cows from hurting each other, FJ want to assign the cows to the stalls, such that the minimum distance between any two of them is as large as possible. What is the largest minimum distance?

Input

* Line 1: Two space-separated integers: N and C

* Lines 2..N+1: Line i+1 contains an integer stall location, xi

Output

* Line 1: One integer: the largest minimum distance

Sample Input
5 3
1
2
8
4
9
Sample Output
3
Hint

OUTPUT DETAILS:

FJ can put his 3 cows in the stalls at positions 1, 4 and 8, resulting in a minimum distance of 3.

Huge input data,scanf is recommended.

题解

看到最大化最小值或者最小化最大值,基本都是二分答案的思想,即先二分知道了答案,再判断这个答案是否可行,可行就向右(左)二分找新的答案继续判断,这个题也是这样,先对奶牛的位置排序,二分奶牛之间的距离,如果这头奶牛距离上一次安放的奶牛大于二分的距离就放上,看最后是否放够了C个奶牛。

AC代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#define N 100050
using namespace std;
typedef long long ll;
ll a[N];
int n, c;
bool check(ll x) {
    ll pos = a[1];
    int tmp = c;
    tmp--;
    for (int i = 2; i <= n; i++) {
        if (a[i] >= pos + x) {
            pos = a[i];
            if (tmp > 0) tmp--;
            if (tmp == 0) break;
        }
    }
    return tmp == 0;
}
int main() {
    scanf("%d%d", &n, &c);
    for (int i = 1; i <= n; i++) {
        scanf("%lld", &a[i]);
    }
    sort (a + 1, a + n + 1);
    ll l = 0, r = 1000000050;
    ll mid;
    ll ans = 0;
    while (l <= r) {
        mid = (l + r) >> 1;
        if (check(mid)) {
            ans = max(ans, mid);
            l = mid + 1;
        }
        else {
            r = mid - 1;
        }
    }
    cout << ans << endl;
    return 0;
}

类型二:最小化最大值

思想同最大化最小值

例题 POJ-3104 Drying

此题有一定思维难度,单独写一篇题解,地址https://www.cnblogs.com/artoriax/p/10375508.html

类型三:最大化平均值

这种类型的题目需要转换一下

例题 POJ-3111 K Best

此题有一定思维难度,单独写一篇题解,地址https://www.cnblogs.com/artoriax/p/10375709.html

三分

例题 HDU-2899 Strange fuction

题目链接

https://vjudge.net/problem/HDU-2899

题面

Description

Now, here is a fuction:
F(x) = 6 * x^7+8x^6+7x^3+5x^2-yx (0 <= x <=100)
Can you find the minimum value when x is between 0 and 100.

Input

The first line of the input contains an integer T(1<=T<=100) which means the number of test cases. Then T lines follow, each line has only one real numbers Y.(0 < Y <1e10)

Output

Just the minimum value (accurate up to 4 decimal places),when x is between 0 and 100.

Sample Input

2
100
200

Sample Output

-74.4291
-178.8534

题意

函数的一项系数未知,给定这个系数的值,找出函数的极小值点x

题解

三分模版题,每次舍弃离极值点远的部分

AC代码

#include<bits/stdc++.h>
#define eps 1e-8
using namespace std;
double y;
double calc(double x) {
    return 6 * pow(x, 7) + 8 * pow(x, 6) + 7 * pow(x, 3) + 5 * x * x - y * x;
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%lf", &y);
        double l = 0, r = 100;
        double midl, midr;
        while (r - l > eps) {
            midl = (l + r) / 2;
            midr = (midl + r) / 2;
            double cmidl = calc(midl);
            double cmidr = calc(midr);
            if (cmidl < cmidr) {
                r = midr;
            }
            else l = midl;
        }
        printf("%.4f\n", calc(midl));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/artoriax/p/10375773.html
0条评论
添加一条新回复