二分法专题题解

upper_bound(first, last, value): Returns an iterator pointing to the first element in the range [first,last) which compares greater than val.
lower_bound(first, last, value): Returns an iterator pointing to the first element in the range [first,last) which does not compare less than val.

A - 4 Values whose Sum is 0

we need to find how many quadruplet ( a , b , c , d ) ∈ A × B × C × D (a,b,c,d) \in A \times B \times C \times D (a,b,c,d)A×B×C×D satisfy a + b + c + d = 0 a+b+c+d=0 a+b+c+d=0, in other words, we need to find how many equations satisfy a + b = − ( c + b ) a+b=-(c+b) a+b=(c+b), so we can compute the result of all pairs(a+b), then BinarySearch in the result of all pairs(-(c+b)). time complexity is O ( n 2 l o g n ) O(n^2logn) O(n2logn). In the last lesson, I tell you can use lower_bound() and upper_bound() function in C++ STL instead of implement the corresponding code yourself.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 4e3+100;

struct Quad{
    int a, b, c, d;
}quad[maxn];

int ab[maxn*maxn];
int cd[maxn*maxn];

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        for(int i = 0; i < n; i++)
            scanf("%d%d%d%d", &quad[i].a, &quad[i].b, &quad[i].c, &quad[i].d);
        int tot = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                ab[tot++] = quad[i].a + quad[j].b;
        tot = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                cd[tot++] = -quad[i].c - quad[j].d;
        sort(cd, cd+tot);
        int ans = 0;
        for(int i = 0; i < tot; i++)
            ans += upper_bound(cd, cd+tot, ab[i]) - lower_bound(cd, cd+tot, ab[i]);
        printf("%d\n", ans);
    }
    return 0;
}

B - Can you find it?

Similar method to solve this problem.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 505;

int A[maxn], B[maxn], C[maxn];

int check[maxn*maxn];

int main(){
    int L, M, N, Case = 0;
    while(scanf("%d%d%d", &L, &M, &N) != EOF){
        for(int i = 0; i < L; i++) scanf("%d", &A[i]);
        for(int i = 0; i < M; i++) scanf("%d", &B[i]);
        for(int i = 0; i < N; i++) scanf("%d", &C[i]);
        int tot = 0;
        for(int i = 0; i < L; i++)
            for(int j = 0; j < M; j++)
                check[tot++] = A[i] + B[j];
        sort(check, check + tot);
        int S, X;
        scanf("%d", &S);
        printf("Case %d:\n", ++Case);
        for(int i = 0; i < S; i++){
            int flag = 0;
            scanf("%d", &X);
            for(int j = 0; j < N; j++)
                if(binary_search(check, check+tot, X-C[j])){ flag = 1; break;}
            if(flag) puts("YES");
            else puts("NO");
        }

    }
    return 0;
}

C - Median

First,you can use binary search to find the right median. After than, you should compute how many differences are larger than the median. In this process, because X is in order after sorting, you can also use the idea of binary search。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+100;
#define LL long long

int X[maxn];

bool judge(int n, int val, LL cnt){
    LL tot = 0;
    for(int i = 0; i < n-1; i++){
        tot += n - (lower_bound(X+i, X+n, X[i]+val)-X);
    }
    return tot > cnt;
}

int main(){
    int n;
    while(scanf("%d", &n) != EOF){
        for(int i = 0; i < n; i++) scanf("%d", &X[i]);
        sort(X, X+n);
        int l = 0, r = X[n-1]-X[0];
        while(l < r){
            int mid = (l+r+1)>>1;
            if(judge(n, mid, (LL)n*(n-1)>>2)) l = mid;
            else r = mid-1;
        }
        printf("%d\n", r);
    }
    return 0;
}

D - A Cubic number and A Cubic Number

when you solve this problem, you need to simplify the formula. x 3 − y 3 = ( x − y ) × ( x 2 + x × y + y 2 ) x^3-y^3=(x-y)\times(x^2+x\times y+y^2) x3y3=(xy)×(x2+x×y+y2), so when x − y &gt; 1 x-y&gt;1 xy>1, x 3 − y 3 x^3-y^3 x3y3 mustn’t be a prime, because it has a divisor ( x − y ) (x-y) (xy). we draw a conclusion that x − y = 1 x-y=1 xy=1. After above analytizing, we can store all ( x + 1 ) 3 − x 3 = 3 ∗ i 2 + 3 × i + 1 (x+1)^3-x^3=3*i^2+3\times i+1 (x+1)3x3=3i2+3×i+1 in an array, then binary search corresponding value.

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 1e6+100;

LL cube[maxn], tot = 0;

void init(){
    for(LL i = 1; i < maxn; i++)
        cube[tot++] = 3*i*i + 3*i + 1;
}

int main(){
    init();
    int T;
    scanf("%d", &T);
    while(T--){
        LL p;
        scanf("%lld", &p);
        if(binary_search(cube, cube+tot, p)) puts("YES");
        else puts("NO");
    }
    return 0;
}

E - I Count Two Three

Build table and binary search.

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn = 1e7+5;
LL arr[maxn];

//

int init(){
    arr[0] = 1LL;
    LL cur = 0;
    for(int a = 0; a <= 32; a++)
        for(int b = 0; b <= 21; b++)
            for(int c = 0; c <= 20; c++)
                for(int d = 0; d <= 19; d++){
                    double x = pow(2.0,a)*pow(3.0,b)*pow(5.0,c)*pow(7.0,d);
                    if(x > 1e9) continue;
                    else arr[cur++] = (int)x;
                }
    sort(arr, arr+cur);
    return cur;
}

int main(){
    int T, n, right;
    right = init();
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        int l = 0, r = right-1;
        while(l < r){
            int mid = (l+r)/2;
            if(arr[mid] < n) l = mid+1;
            else r = mid;
        }
        printf("%I64d\n", arr[r]);
    }
    return 0;
}

F - Pie

#include <stdio.h>
#include <math.h>
#include <algorithm>
const int maxn = 1e4+100;
const double pi = acos(-1.0);
const double eps = 1e-4;

int r[maxn];
int T, N, F;

bool judge(double V){
    int tot = 0;
    for(int i = 0; i < N; i++){
        double x = pi*r[i]*r[i]/V;
        tot += floor(x);
    }
    return tot >= (F+1);
}

double Binary_Search(double R){
    //对我和我的朋友所能得到的饼的最大体积进行二分。
    double l = 0.0, r = R;
    while(fabs(r-l) > eps){
        double mid = (l+r)/2.0;
        if(judge(mid)) l = mid;
        else r = mid;
    }
    return l;
}


int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d %d", &N, &F);
        int index = 0;
        for(int i = 0; i < N; i++){
            scanf("%d", &r[i]);
            if(r[i] >= r[index]) index = i;
        }
        printf("%.4lf\n", Binary_Search(pi*r[index]*r[index]));
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值