二分。

最近状态不好,采用边写边记录的方式,看能否解决一下。

二分:

Hdu 2141 Can you find it?(easy) 点击打开链接

二分查找,给三个数列(a,b,c),从每个数列中各找一个,看能否和为X。

转化为a+b=X-c,将a+b的可能找出来,排序。(n^2+2*n^2*logn的时间复杂度)

二分查找等于X-c的。(n*logn的时间复杂度)由于n最大为500,所以时间复杂度还是可以。

代码:

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

const int Len=503;
const int MLen=250003;
int x,L,N,M,a[Len],b[Len],c[Len],d[MLen],top;

bool Binary_search(int y){
    int low=0,high=top;
    while(high>=low){
        int mid=(high+low)/2;
        if(d[mid]==y) return true;
        if(d[mid]>y) high=mid-1;
        else low=mid+1;
    }
    return false;
}

int main(){
    int k=1;
    while(~scanf("%d%d%d",&L,&N,&M)){
        for(int i=0;i<L;i++)
        scanf("%d",&a[i]);
        for(int i=0;i<N;i++)
        scanf("%d",&b[i]);
        for(int i=0;i<M;i++)
        scanf("%d",&c[i]);
        top=0;
        for(int i=0;i<L;i++){
            for(int j=0;j<N;j++)
            d[top++]=a[i]+b[j];
        }top--;
        sort(d,d+top);
        int s;
        scanf("%d",&s);
        printf("Case %d:\n",k++);
        while(s--){
            scanf("%d",&x);
            bool flag=false;
            for(int i=0;i<M;i++){
                if(Binary_search(x-c[i])){
                    flag=true;
                    break;
                }
            }
            if(flag) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

比较典型的二分查找吧。。!!


Hdu 2899   strange faction点击打开链接

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

简短的题目,直接贴这儿了。意思就是给一个y值,求x从0到100的最小值。

对其求导,等其斜率函数:F‘(x)=42*x^6+48*x^5+21*x^2+10*x-y;那么就是求其斜率函数为0的时候的值。(这个...不要解释了)

也就是求42*x^6+48*x^5+21*x^2+10*x=y,可知F‘(x)=42*x^6+48*x^5+21*x^2+10*x,是单调递增的,所以,该题可以二分法来求该方程的解。

Ps,函数中用二分法求解方程的解时,需要要求该函数是单调的。!!

代码:

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

const int Len=503;
const int MLen=250003;
int x,L,N,M,a[Len],b[Len],c[Len],d[MLen],top;

bool Binary_search(int y){
    int low=0,high=top;
    while(high>=low){
        int mid=(high+low)/2;
        if(d[mid]==y) return true;
        if(d[mid]>y) high=mid-1;
        else low=mid+1;
    }
    return false;
}

int main(){
    int k=1;
    while(~scanf("%d%d%d",&L,&N,&M)){
        for(int i=0;i<L;i++)
        scanf("%d",&a[i]);
        for(int i=0;i<N;i++)
        scanf("%d",&b[i]);
        for(int i=0;i<M;i++)
        scanf("%d",&c[i]);
        top=0;
        for(int i=0;i<L;i++){
            for(int j=0;j<N;j++)
            d[top++]=a[i]+b[j];
        }top--;
        sort(d,d+top);
        int s;
        scanf("%d",&s);
        printf("Case %d:\n",k++);
        while(s--){
            scanf("%d",&x);
            bool flag=false;
            for(int i=0;i<M;i++){
                if(Binary_search(x-c[i])){
                    flag=true;
                    break;
                }
            }
            if(flag) printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

典型的函数求解时,用到的二分求解。


Hdu 3400 Line belt 点击打开链接

因为是在做二分做题,好不容易理解了题意。

说是,给两条线段AB,CD,问从A到D的最短时间,因为在AB,CD上的速度和在其他地方的速度是不一样的,所以,可能是,在AB,CD上各走一部分的路程,列出一个关系式,一个两个未知数的方程,二分?不会啊。

百度一下思路:三分,真心不会。马上就学!!


Hdu 2289 Cup 点击打开链接

说是,给一个杯子(圆台),里面有水,让求水的高度。

擦,圆台体积,表面积神马的,忘的一塌糊涂啊。复习一下!!!

然后就是用水的高度来表示一下水面的半径!!

代码:

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

const double pi=3.1415926535898;
const double eps=1e-9;
double r,R,H,V;

double f(double h){
//    return (pi*h*(r*r+((h*(R-r)+r*H)/H*(h*(R-r)+r*H)/H)+(h*(R-r)+r*H)/H*r))/3.0;
    return (pi*h*(pow(r,2)+pow((h*(R-r)+r*H)/H,2)+(h*(R-r)+r*H)/H*r))/3.0;
}

double Binary_search(){
    double low=0,high=H;
    while(fabs(high-low)>eps){
        double mid=(high+low)/2;
        double tmp=f(mid);
//        printf("%.9lf\n",)
        if(tmp==V) return mid;
        if(tmp>V) high=mid;
        else low=mid;
    }
    return (high+low)/2;
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%lf%lf%lf%lf",&r,&R,&H,&V);
        printf("%.6lf\n",Binary_search());
    }
    return 0;
}

思路很是清晰,就是体积+面积神马的公式忘的一干二净了。记住啊!!

Hdu 2446 Shell Pyramid 点击打开链接

题意很简单(虽然题目很长),就是 1 2 3 4  5 ....每堆炮弹的数量,然后问你,编号为s的炮弹的Layer,Row,Cloumn。

比较麻烦的就是其数据范围比较大,2^63,大数据需要注意的小bug有很多。

该题用到的是打表二分查找。


一开始,我一直顾忌,得打多少?其实,应该仔细计算一下,s最大为2^63次方,?根据前n项和的通项公式就可以得到!!think more。

代码:

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

typedef unsigned __int64 LL;
const unsigned int N=3810776;
LL sum[N];

LL Binary_search(LL x){
    LL low=0,high=N-1;
    while(high>=low){
        LL mid=(high+low)/2;
        if(sum[mid]==x) return mid;
        if(sum[mid]>x) high=mid-1;
        else low=mid+1;
    }
    return low;
}

int main(){
    sum[0]=0;sum[1]=1;
    for(LL i=2;i<N;i++){
        sum[i]=i*(i+1)*(i+2)/6;
    }
    LL n,T;
    scanf("%I64u",&T);
    while(T--){
        scanf("%I64u",&n);
        LL Layer=Binary_search(n);
        LL tmp=n-(Layer*Layer*Layer-Layer)/6;
        LL Row=(LL)sqrt(tmp*2);
        if(Row*(Row+1)/2<tmp) Row++;
        printf("%I64u %I64u %I64u\n",Layer,Row,tmp-Row*(Row-1)/2);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值