二分。三分

https://vjudge.net/contest/271273#problem/A

哎,后面有个四舍五入的问题。

if( (int) (right * 1000) % 10 >= 5)
right -= 0.005;
printf("%.2f\n", right);

 

.2f是默认四舍五入的,上面一段代码是取消四舍五入。

 


https://vjudge.net/contest/271273#problem/M

https://vjudge.net/contest/271273#problem/J

三分

https://vjudge.net/contest/271273#problem/N

数学题,不会

 

https://cn.vjudge.net/contest/260332#status/xiayuyang/A

二分尺取

一般如果是那种求精度的,直接lb.ub = mid; ub - lb < 1ex;或者用for循环x次(一般为100,2的一百次方够了)

如果是那种求 lb < ub,这种要lb + 1, ub - 1;

最小值最大化的二分区间是右闭左开(L,R],每次二分的中心为M=(L+R+1)/2;最大值最小化的二分区间是左闭右开,[L,R),每次二分的中心为M=(L+R)/2。

因为。。。。

二分时间复杂度nlogn;

二分法:适用于单调函数,单调增或单调减

三分法:适用于单峰凸性函数,如二次函数,或者是要求两个点

http://www.cnblogs.com/xiaowuga/p/8609943.html

 

 poj 3273  Monthly Expense  最小化最大值

题目意思:

给出John在N个月中每个月的花费,John想将N个月分成M个组。
每组的月份是连续的,同一组的花费被相加起来,求所有分组情况中最高花费的最低值。
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int maxm = 1e5 + 5;
int a[maxm];
int n, m;

bool fun(int x, int val) {
for(int i = 0; i < n; i++) {
int res = a[i];
if(res <= x) {
    while(res <= x) {
        i++;
        res += a[i];
        val--;
        if(i >= n) break;
    }
    val++;
    i--;
//    printf("vsdnvs\n");
}
else {
    return false;
}
}
if(val <= 0) return true;
else return false;
}

int main() {
scanf("%d%d", &n, &m);
for(int i = 0; i < n; i++) {
    scanf("%d", &a[i]);
}
int l = 0, r = 1e9, mid;
while(l <= r) {
mid = (l + r) / 2;
if(fun(mid, n - m)) {
    r = mid - 1;
}
else {
    l = mid + 1;
}
}
if(fun(l, n - m)) printf("%d\n", l);
else if(fun(r, n - m)) printf("%d\n", r);
//printf("%d\n", fun(500, n - m));

return 0;
}

River Hopscotch  最大化最小值

牛过河,有很多石头,起点为1,终点为n,移去m快石头,求之后的最小值。

 

#include<cstdio>
#include<algorithm>
#include<cstring>

using namespace std;
const int maxm  = 50010;
int dis, n, m, a[maxm];

bool fun(int x, int val) {
for(int i = 1; i <= n + 1; i++) {
    int res = a[i - 1];
    if(a[i] - res < x) {
        while(a[i] - res < x) {
            i++;
            val--;
            if(i > n + 1) break;
        }
    }
}
if(val < 0) return false;
else return true;
}

int main() {
scanf("%d%d%d", &dis, &n, &m);
for(int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
}
a[n + 1] = dis;
sort(a, a + 2 + n);
int l = 0, r = 1e9, mid;
while(l <= r) {
    mid = (l + r + 1) / 2;
    if(fun(mid, m)) {
        l = mid + 1;
    }
    else {
        r = mid - 1;
    }
}
if(fun(r, m)) printf("%d\n", r);
else if(fun(l, m)) printf("%d\n", l);


return 0;
}

 

Flyer

 HDU - 4768 想法二分,一些人给 学校所有人发传单,a,b,c,发给a + k* c;k大于等于0,序号不小于c,求拿到奇数的那个人。

n个社团派发传单,有a,b,c三个参数,派发的规则是,派发给序号为a,a+c....a+k*c,序号要求是小于等于b
这其中,有一个学生只收到了奇数传单,要求找出这个学生的编号与得到的传单数目

思路:如果使用异或运算,也还是比较简单的,但是这样的话所花费的时间就比较长,正确的做法是使用二分
使用二分来划分区间,由于是每个社团得到的序列都是等差数列,所以我们很容易能得到区间派发的传单数
如果是奇数,那么所求的人肯定在左区间,否则在右区间,这样二分下去找到答案
https://blog.csdn.net/libin56842/article/details/25741317

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;


typedef long long ll;
const int maxm = 2e4 + 5;

ll n, A, B, C, a[maxm], b[maxm], c[maxm];

bool solve(ll d) {
ll num = 0;
for(int i = 0; i < n; i++) {
    if(d >= a[i]) {
        ll x = min(d, b[i]);
        num += (x - a[i]) / c[i] + 1;
    }
}
return num % 2;
}

ll  check(ll d) {
ll num = 0;
for(int i = 0; i < n; i++) {
    if(d >= a[i] && d <= b[i]) {
        if( (d - a[i]) % c[i] == 0 ) num++;
    }
}
return num;
}

int main() {

while(~scanf("%lld", &n)) {
    for(int i = 0; i < n; i++) {
        scanf("%lld%lld%lld", &a[i], &b[i], &c[i]);
    }

    ll lb = -1, ub = 1ll << 32, ans = 0;
    while(lb <= ub) {
        ll mid =  (ub + lb) / 2;
        if(solve(mid)) {
            ub = mid - 1;
            ans = mid;
        }
        else lb = mid + 1;
    }
    if(check(ans) % 2) printf("%lld %lld\n", ans, check(ans));
    else printf("DC Qiang is unhappy.\n");

}
return 0;
}

https://vjudge.net/contest/271273#problem/J

看一下代码 三分

A Star not a Tree? POJ - 2420

和poj1379差不多 
很多个点,求一个点到所有点的距离之和最小。

#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;

typedef pair<double, double> pii;
pii p[105];
int n;

double sum(double x, double y) {
double num = 0;
for(int i = 0; i < n; i++) {
    num += sqrt( (x - p[i].first) * (x - p[i].first) + (y - p[i].second) * (y - p[i].second) );

}
return num;
}

double check(double d) {
double lb = 0, ub = 10001;
for(int i = 0; i < 100; i++) {
    double midy = (lb + ub) / 2.0;
    double midmidy = (midy + ub) / 2.0;
    if(sum(d, midy) < sum(d, midmidy)) {
        ub = midmidy;
    }
    else lb = midy;
}
return min(sum(d, ub), sum(d, lb));
}

int main() {

scanf("%d", &n);
for(int i = 0; i < n; i++) {
    scanf("%lf%lf", &p[i].first, &p[i].second);

}
double lb = 0, ub = 10001;
for(int i = 0; i < 100; i++) {

    double midx = (lb + ub) / 2.0;
    double midmidx = (midx + ub) / 2.0;
    if(check(midx) < check(midmidx)) {
        ub = midmidx;
    }
    else lb = midx;
}
printf("%.0f\n", min(check(lb), check(ub)));

return 0;
}

UmBasketella

 POJ - 3737 

已知圆锥面积求体积,高

公式:圆锥面积=PI * r * r + PI * r * l (l为母线长度)

   l * l = h * h + r * r.

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double PI = acos(-1.0), eps = 1e-6;
double s;
double cal(double r)
{
    double R = s/(PI*r) - r;
    double h = sqrt(R*R - r*r);
    return h*PI*r*r/3;
}
int main()
{
    while(scanf("%lf", &s) != EOF)
    {
        double left = 0, right = sqrt(s/(2*PI)), v;
        while(right - left > eps)
        {
            double middle = (left + right) / 2;
            double middleright = (middle + right) / 2;
            double v1 = cal(middle);
            double v2 = cal(middleright);
            if(v1 >= v2)
            {
                right = middleright;
                v = v1;
            }
            else
            {
                left = middle;
                v = v2;
            }
        }
        double r = right;
        double H = sqrt((s/(PI*r) - r)* (s/(PI*r) - r) - r*r);
        printf("%.2f\n%.2f\n%.2f\n", v, H, r);
    }
    return 0;
}

 

Light Bulb

 数学题(主要是退公式) 精度尽量改小点。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t;
double D,H,h;
double fun2(double x) {
    return D - x + H - (H - h) * D / x;
}

double fun(double l, double r) {
    double mid, midmid, res;
    while(r - l >= 1e-9) {
        mid =(l + r) / 2;
        midmid = (mid + r) / 2;
        double a = fun2(mid);
        double b = fun2(midmid);
        if(a < b) {
            l = mid;
            res = fun2(mid);
        }
        else {
            r = midmid;
            res = fun2(midmid);
        }
    }
    return res;
}
int main() {
    scanf("%d", &t);
    while(t--) {
        scanf("%lf%lf%lf", &H, &h, &D);
        printf("%.3f\n", fun((H - h) * D / H, D));
    }
    return 0;
}

 https://vjudge.net/contest/283149#problem/A专题

posted @ 2018-11-19 23:40  downrainsun  阅读(176)  评论(0编辑  收藏  举报