二分法练习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\n",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\n",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\n",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\n",(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]='\0';
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\n",r-l+1);
66         else printf("%d\n",r-l);
67     }
68     return 0;
69 }
Code

 

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

 

posted @ 2016-08-04 22:50  GraceSkyer  阅读(616)  评论(0编辑  收藏  举报

~~~~~~ACM大牛语录,激励一下~~~~~~

为了世界的和平,为了女生的安全,我拼命做题,做题,做题!

用最短的时间,刷最多的题!

给我一滴泪,我就看到了你全部的海洋!

seize the hour, seize the day.

人生难免有无奈,幸福走远了,或是感叹幸福来迟了.其实我一直相信,无论手中的幸福是多么微不足道的感觉,我会把握住那每一分,每一秒,当幸福依旧像那百鸟般飞逝,终究无法掌握时,我会感谢它,曾经降临过!

A自己的题,让别人郁闷去吧

WA肠中过,AC心中留 TLE耳边过,AC特别牛

天然的悲苦和伤逝,过去有过,以后还会有

^*^一步一步往上爬^*^

AC就像练级,比赛就像PK. 练级不如PK好玩

其实,世上本没有ACM,AC的人多了,也便有了!

AC无止尽~ Seek you forever~

找呀找呀找水题,找到一个AC一个呀!

AC是检验程序的唯一标准。

真的猛士,敢于直面惨淡的人生,敢于正视淋漓的鲜血……