zoukankan      html  css  js  c++  java
  • 二分法练习1

    开始预习二分法啦~00B7ADBF

    poj3273 Monthly Expense (二分,最大值最小化)

    题意:将N个账款分割成M个财务期,使得每个分期账款和的最大值最小。

    题解:贪心思想,二分法。上界为N天花费总和,下界为每天花费的最大值。根据mid值遍历n天花费看是否满足M各财务期条件

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int main(){
     5     int n,m,i,cnt,a[100001],ma=0,s=0;
     6     scanf("%d%d",&n,&m);
     7     for(i=0;i<n;++i){
     8         scanf("%d",&a[i]);
     9         ma=max(a[i],ma);
    10         s+=a[i];
    11     }
    12     int l=ma,r=s,mid;
    13     while(l<r){
    14         mid=(l+r)>>1;
    15         cnt=1;
    16         for(s=i=0;i<n;++i){
    17             s+=a[i];
    18             if(s>mid){cnt++;s=a[i];}
    19         }
    20         if(cnt<=m) r=mid;
    21         else l=mid+1;
    22     }
    23     printf("%d
    ",l);
    24     return 0;
    25 }
    Code

    poj3258 River Hopscotch (二分,最小值最大化)

    题意:一条长为L的河,除了起始点还有N个石子,分别距离起点Di,求去掉M个石子后相邻石子最小距离的最大值。

    题解:上界为河长L,下界为初始时两相邻石子间最小距离,根据mid值遍历N个石子看是否满足移除M石子的条件。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int main(){
     5     int L,n,m,i,l,r,mid,cnt,s,a[50002];
     6     scanf("%d%d%d",&L,&n,&m);
     7     for(i=1;i<=n;++i) scanf("%d",&a[i]);
     8     a[0]=0;
     9     sort(a,a+n+1);
    10     l=r=L;
    11     for(i=1;i<=n;++i) l=min(l,a[i]-a[i-1]);
    12     while(l<r){
    13         mid=(l+r+1)/2;//注意+1保证left每次都增大
    14         cnt=s=0;
    15         for(i=1;i<=n;++i){
    16             s+=(a[i]-a[i-1]);
    17             if(s<mid) cnt++;
    18             else s=0;
    19         }
    20         if(cnt<=m) l=mid;
    21         else r=mid-1;
    22     }
    23     printf("%d
    ",l);
    24     return 0;
    25 }
    Code

    poj1905 Expanding Rods (二分,几何)

    题意:一根棍子,受热后长度会变为L' = (1+n*C)*L(棍子变为圆弧)。问受热后棍子的中点距离地面的高度h为多少。

    题解:做这题我复习了一下相交弦定理(初中学的01C5A3A7都快忘了):若AB是直径,CD垂直AB于点P,则 =PA·PB。

    直接二分高度,算出半径和弧度,然后将算出的弧长与实际弧长比较。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #define eps 1e-4
     5 using namespace std;
     6 int main(){
     7     double L,n,c,L1,sita,l,r,mid,R;
     8     while(scanf("%lf%lf%lf",&L,&n,&c)==3){
     9         if(L<0||n<0||c<0)break;
    10         L1=(1+n*c)*L;
    11         l=0; r=L/2;
    12         while(l+eps<r){
    13             mid=(l+r)/2;
    14             R=L*L/mid/8+mid/2;//相交弦定理
    15             sita=2*asin(L/2/R);
    16             if(sita*R<=L1) l=mid;
    17             else r=mid;
    18         }
    19         printf("%.3f
    ",l);
    20     }
    21     return 0;
    22 }
    Code

    poj3122 Pie (二分)

    题意:有n块高度为1,半径不等的圆柱形披萨,要将其“平均”(每份体积相等,形状无要求,但必须每份是从同一个披萨上得到的)分给(f+1)人。

    题解:下界为0,上界为最大的披萨的尺寸,二分尺寸看能分给多少人。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cmath>
     4 #define pi 3.14159265359//背一下咯
     5 #define eps 1e-6
     6 using namespace std;
     7 int main(){
     8     int t,i,n,f,a[10001],R,cnt;
     9     double l,r,mid;
    10     scanf("%d",&t);
    11     while(t--){
    12         scanf("%d%d",&n,&f);
    13         f++;//总人数记得加上自己
    14         l=r=0;
    15         for(i=0;i<n;++i){
    16             scanf("%d",&R);
    17             a[i]=R*R;
    18             r=max(1.*a[i],r);
    19         }
    20         while(l+eps<r){
    21             mid=(l+r)/2;
    22             cnt=0;
    23             for(i=0;i<n;++i)
    24                 cnt+=(int)(a[i]/mid);
    25             if(cnt>=f) l=mid;
    26             else r=mid;
    27         }
    28         printf("%.4f
    ",(double)mid*pi);
    29     }
    30     return 0;
    31 }
    Code

    poj2413 How many Fibs? (高精度,二分)

    题意:定义fibonacci数列前两项f[1] = 1,f[2] = 2。现在给你一个区间[a,b],a <= b <= 10^100。问:区间[a,b]之间有多少个fibonacci数。

    题解:先算出480个斐波那契数(第480个斐波那契数是101位了)。二维数组F[i][]表示第i个斐波那契数,二分查找a,b位置,如果找到的位置不是斐波那契数,则返回第一个比它大的斐波那契数的位置,注意对b判断作标记。

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 const int N=482;
     7 const int M=102;
     8 int F[N][M],f;
     9 char Fi[N][M],a[M],b[M];
    10 void Fib(){
    11     int i,j,k;
    12     F[1][0]=1;F[2][0]=2;
    13     for(i=3;i<N;++i){
    14         for(j=0;j<M;++j){
    15             F[i][j]+=F[i-1][j]+F[i-2][j];
    16             if(F[i][j]>=10){
    17                 F[i][j+1]+=F[i][j]/10;
    18                 F[i][j]%=10;
    19             }
    20         }
    21     }
    22     for(i=1;i<N;++i){
    23         for(j=M-1;j>=0;--j){//清除前导0
    24             if(F[i][j]==0)continue;
    25             else break;
    26         }
    27         k=0;
    28         while(j>=0){
    29             Fi[i][k++]=F[i][j]+'0';
    30             j--;
    31         }
    32         Fi[i][k]='';
    33     }
    34 }
    35 int cmp(char*a,char*b){
    36     int La=strlen(a);
    37     int Lb=strlen(b);
    38     if(La!=Lb) return La<Lb?-1:1;
    39     else return strcmp(a,b);
    40 }
    41 int bi_search(char *s){
    42     int l=1,r=480,mid;
    43     while(l<=r){
    44         mid=(l+r)/2;
    45         int x=cmp(s,Fi[mid]);
    46         if(x==0){
    47             f=1;
    48             return mid;
    49         }
    50         else if(x<0)
    51             r=mid-1;
    52         else l=mid+1;
    53     }
    54     return l;
    55 }
    56 int main(){
    57     Fib();
    58     int l,r;
    59     while(~scanf("%s %s",a,b)){
    60         if(strcmp(a,"0")==0&&strcmp(b,"0")==0)
    61             break;
    62         l=bi_search(a);
    63         f=0;
    64         r=bi_search(b);
    65         if(f) printf("%d
    ",r-l+1);
    66         else printf("%d
    ",r-l);
    67     }
    68     return 0;
    69 }
    Code

    【如有错误,敬请指正,欢迎交流】

  • 相关阅读:
    轻节点如何验证交易的存在
    梯度爆炸/消失与初始化参数
    归一化能够加速训练的原因
    正则化可以防止过拟合的原因
    关于周志华《机器学习》中假设空间规模大小65的计算
    linux学习0001
    目标检测算法
    opencv安装与卸载
    前端学习02
    前端学习01
  • 原文地址:https://www.cnblogs.com/GraceSkyer/p/5738686.html
Copyright © 2011-2022 走看看