2019_GDUT_新生专题I选集 二分
H
题意:
MaratonIME正在聚集,开始另一项小组练习。 这次,Renzo决定奖励解决问题的学生糖果。 MaratonIME的成员开始猜测Renzo带了多少糖果。 对于每个问题,Renzo都回答了糖果的数量是否更高,更低或等于所要求的数量。
Breno注意到糖果的数量可能很高,因此决定将查询数量限制为50。
Renzo至少购买了1个,最多不超过109个糖果。 查找不超过50个问题的Renzo购买了多少糖果。
题目链接:http://codeforces.com/gym/101375/problem/H
二分模板,我最开始是死在交互上面的
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
int main(){
int left=0,right=1000000001;
char c;
while (1){
int mid=(left+right)/2;
cout<<"Q "<<mid<<endl;//endl会自动刷新缓冲区
c=getchar();
getchar();
if (c=='<') right=mid;
else if (c=='>') left=mid;
else if (c=='=')return 0;
}
}
I
题意:农夫 John 建造了一座很长的畜栏,它包括NN (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,…,xN (0 <= xi <= 1,000,000,000). 但是,John的C (2 <= C <= N)头牛们并不喜欢这种布局,而且几头牛放在一个隔间里,他们就要发生争斗。为了不让牛互相伤害。John决定自己给牛分配隔间,使任意两头牛之间的最小距离尽可能的大,那么,这个最大的最小距离是什么呢
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1734
刚开始做这题可能无从下手,但是观察一下,设任意两头牛之间的最短距离为X,当X比最大的最小距离小的时候必定能找到一种分配隔间的方式使得距离任意两头牛的距离大于等于X,当X大于最大的最小距离时则一定找不到。感觉在说废话
所以只需要对任意两头牛之间的距离X进行二分即可,
对于判断任意两头牛之间的距离是否能大于X,只要贪就好了,先把一头牛放到最前面的隔间,然后在第一个与前一头牛的隔间距离大于等于X的隔间放下一头牛
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m;
int a[1000005];
//check用于检测任意两头牛的距离能否大于等于X
bool check(int x){
int y=a[1],k=m-1,i=2;
while (k&&i<=n)
{
if (a[i]-y>=x)
{
k--;
y=a[i];
}
i++;
}
if (k) return false;
else return true;
}
//二分答案
void search(int left,int right){
while (left+1<right)
{
int mid=(left+right)/2;
if (check(mid)) left=mid;
else right=mid;
}
printf("%d\n",left);
}
int main(){
scanf("%d %d",&n,&m);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
search(1,500000001);
}
J
题意:当将长度为L的细棒加热n度时,它会膨胀到新的长度L’=(1 + n * C)* L,其中C是热膨胀系数。
将细杆安装在两个实心壁上然后加热时,细杆膨胀并呈圆形扇形,原始杆为扇形的弦。您的任务是计算杆中心位移的距离。
题目链接:http://poj.org/problem?id=1905
把题目里面的数学关系找出来之后,随便选一个数二分即可,我这里直接对杆的中心位移距离进行二分,注意一下精度问题,再特判下一杆长度为0的情况即可。
代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#include<cstring>
using namespace std;
int main(){
double l,n,c;
while (scanf("%lf %lf %lf",&l,&n,&c))
{
if (l==-1&&n==-1&&c==-1) break;
if (l==0)
{
printf("0.000\n");
continue;
}
double L=(1+n*c)*l;
double left=0,right=l/2.0;
while (right-left>=1e-8)
{
double mid=(right+left)/2.0;
double r=l*l/mid/8+mid/2,d=asin(l/2/r),LL=r*2.0*d;
if (LL<L) left=mid;
else right=mid;
}
printf("%.3f\n",left);
}
return 0;
}