第二次组队赛 二分&三分全场
这次的比赛是二分&三分专题,说实话以前都没有接触过二分,就在比赛前听渊神略讲了下.......不过做着做着就对二分熟悉了,果然做题是学习的好方法啊~~~~\(≧▽≦)/~啦啦啦,不过我们这组每次都是刚开始垫底,然后才慢慢追上去.......真担心爆零,但是结果还不错,和第一做的题目一样多,差的只是错误率和时间。
A:大意是:给你一个直线和一个弧线,(弧线是圆的一部分),求弧线高出直线的高度。POJ 1905 Expanding Rods
解法:先确定半径的范围再进行二分,r1=l/2,半径不可能再小了,再假设r2=l,求出所对应的弧长,若小于所给的长度,则取l,若大于,则r2=r2*2。再二分取对应的半径,最后带入,求高度差。注意!!!!!在这里半径越大,弧长反而越小!!!!!!还有c,n==0的时候要提出来讲,==0时,弧长=l,直接高度==0;
代码: 16MS
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<math.h>
using namespace std;
double l;
double f(double r) //求弧长
{
return (asin(l/r/)**r); //asin()是反三角函数
}
double g(double r) //求高度差
{
return r-cos(asin(l/(r*)))*r;
}
int main()
{
double c;
double n,r1,r2,mid,sum,w;
while(~scanf("%lf%lf%lf",&l,&c,&n))
{
sum=l*(+n*c);
if(l<&&c<&&n<)
break;
if(c==||n==) //为零的时候要另外讲.......
{
printf("0.000\n");
continue;
}
r1=l/; //半径不可能比l/2更小
r2=l;
while(f(r2)>=sum)//注意,半径越大,所对应的弧长越小......在这错了好久都没检查出来....
r2=*r2;
while(f(r1)-f(r2)>1e-)
{
mid=(r1+r2)/;
w=f(mid);
if(w>sum)
r1=mid;
else if(w<sum)
r2=mid;
else if(w==sum)
break;
}
printf("%.3lf\n",g(mid));
}
return ;
}
B 大意是:给你n个点,找出任意4个点组合,有几个正方形 Squares
思路:先任意找两个点,确定一条边,确定一个正方形,再寻找另外两个点,若能找到则有正方形,计数+1。
代码: 1500MS
#include <stdio.h>
#include <string.h>
#include<iostream>
#include<algorithm>
using namespace std;
int n; /* 点的个数 */
struct Point
{
int x;
int y;
}point[];
bool comp1(Point i,Point j)
{
if(i.x<j.x)
return true;
else if(i.x==j.x)
{
if(i.y<j.y)
return true;
}
return false;
}
//由于点已经按照坐标排序过,所以采用二分查找
//搜索点(x,y)是否存在,存在返回1,否则返回0
int bsearch(int x, int y)
{
int m, s, t;
s = ;
t = n-;
while (s <= t)
{
m = (s+t)/;
if (point[m].x == x && point[m].y == y) return ;
if (point[m].x > x || (point[m].x == x && point[m].y > y))
t = m-;
else
s = m+;
}
return ;
} int main()
{
int x, y, i, j, count;
while (scanf("%d", &n), n)
{
count = ;
for (i = ; i < n; i++)
scanf("%d %d", &point[i].x, &point[i].y);
//插入法对点排序,按照x从小到大,y从小到大,且x优先排列的方式
// 枚举所有边,对每条边的两个顶点可以确定一个唯一的正方形,并求出另外两个顶点的坐标
sort(point,point+n,comp1);
for (i = ; i < n; i++)
for (j = (i+); j < n; j++)
{
//计算第三个点的坐标,搜索其是否存在
x = point[i].y-point[j].y+point[i].x;
y = point[j].x-point[i].x+point[i].y;
if (bsearch(x,y) == )
continue;
//计算第四个点的坐标,搜索其是否存在
x = point[i].y-point[j].y+point[j].x;
y = point[j].x-point[i].x+point[j].y;
if (bsearch(x, y))
count++;
}
printf("%d\n", count/);
}
return ;
}
C 大意是:有m个仓库,n头牛,要把牛放到仓库里,要使两两之间的距离尽可能的大,输出最小的距离。Aggressive cows
不断假设满足的距离;
代码: 110MS
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int N,C,a[];
int juge(int m)
{
int number=,i,frontt=;
for(i=;i<N;i++)
{
if((a[i]-a[frontt])>=m) //判断m是不是最小的距离
{
frontt=i;
number++;
if(number==C) return ;//所有的牛都放进去了,满足
}
}
return ;
} int main()
{
int i,midd,left,right;
scanf("%d%d",&N,&C);
for(i=;i<N;i++)
scanf("%d",&a[i]);
sort(a,a+N);
left=;
right=a[N-]-a[];
while(left<=right) //当l和r交叉错过时就跳出
{
midd=(left+right)/;
if(juge(midd))
left=midd+;//m可能小了
else
right=midd-; //m太大
}
printf("%d\n",left-);
return ;
}
D大意是:给出3个数组,从每个数组中挑一个出来加起来成一个数,问是否能组成所给的数。 Can you find it?
代码: 359MS,时限是3000MS
方法是合并a,b两个数组,变成了只有两个数组去凑数了。
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
int ab[],k;
int f(int x)
{
int l=,r=k,mid;
while(l<=r) //同C的判断方法一样 ,l,r错开就跳出
{
mid=(r+l)/;
if(ab[mid]==x)
return ;
if(ab[mid]<x)
l=mid+;
else
r=mid-;
}
return ;
}
int main()
{
int l,m,n,i,j,o=,s,w,a[],b[],c[];
while(~scanf("%d%d%d",&l,&m,&n))
{
k=;
for(i=;i<l;scanf("%d",&a[i++]));
for(i=;i<m;scanf("%d",&b[i++]));
for(i=;i<n;scanf("%d",&c[i++]));
for(i=;i<l;i++)
for(j=;j<m;j++)
ab[k++]=a[i]+b[j]; //合并a,b两组数
sort(c,c+n);
sort(ab,ab+k);
for(printf("Case %d:\n",o++),scanf("%d",&s);s;s--)
{
scanf("%d",&w);
j=;
for(i=;i<n;i++)
if(f(w-c[i]))
{
j++;
break;
}
if(j)
printf("YES\n");
else
printf("NO\n");
}
}
return ;
}
E 大意是:给出一个方程:8*x^4 + 7*x^3 + 2*x^2 + 3*x + 6 == Y,给出Y,要求求出X,给定X属于[0~100],如果不是在这个范围则输出No solution。
代码: 0MS Can you solve this equation?
#include<stdio.h>
#include<math.h>
int main()
{
int y,T;
scanf("%d",&T);
while(T--)
{
double l=,r=,mid,sum;
scanf("%d",&y);
if(y<||y>) //X小于0和大于100的情况,无解
{
printf("No solution!\n");
continue;
}
while(r-l>1e-)
{
mid=(r+l)/; //二分
sum=pow(mid,)*+*pow(mid,)+mid*mid*+*mid+;
if(sum>y)
r=mid;
else if(sum<y)
l=mid;
else if(sum==y)
break;
}
printf("%.4lf\n",mid);
}
return ;
}
F 大意是:F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100),这个方程,给出Y,求X使得F(X)的值最小,给出X的范围0~100。
思路,因为这不是个单调函数,所以要用三分做。 0MS Strange fuction
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
using namespace std;
double y;
double dis(double x)
{
return *pow(x,)+*pow(x,)+*pow(x,)+*x*x-y*x; //方程
}
int main()
{
double left,right,mid,mmid,t2,t1;
int t;
scanf("%d",&t);
while(t--)
{
mid=;mmid=;
scanf("%lf",&y);
left=;right=;
while(fabs(mid-mmid)>1e-)
{
mid=left/+right/; //三分
mmid=mid/+right/;
t2=dis(mid);t1=dis(mmid);
if(t2>t1)
{
left=mid;
}
else if(t2<t1)
{
right=mmid;
}
else
break;
}
printf("%.4lf\n",t1);
}
return ;
}
G 大意是:给出人在(0,0)这一点,目标在x,y,给出出箭的速度V,求能射到目标的最小角度 Toxophily
有两种方法,一是用纯数学方法,二是用三分+二分。不过都先要找到x,y的关系式:x^2*g/(2*v^2)*tan^2(ß) - x*tan(ß) +y + x^2*g/(2*v^2) = 0;
先是第一种方法,把tanB看做未知数,就变成一个AX^2+BX+C=0的一元二次方程,当△<0时无解,输出-1,△=0时只有一个值,△>0时有两解,取>0,<90的解;取小得那个解。
代码: 0MS
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
const double g=9.8;
int main()
{
int t;
double x,y,v,k,s,d;
cin>>t;
while(t--)
{
scanf("%lf%lf%lf",&x,&y,&v);
k=x*x-*g*x*x/v/v*(y+0.5*g*x*x/v/v); //△
if(k<)
{
printf("-1\n");
}
else
{
s =(x-sqrt(k))*v*v/g/x/x; //小的根
if(s<)
s=(x+sqrt(k))*v*v/g/x/x; //大的根
d=atan(s); //反三角函数
printf("%.6lf\n",d);
}
}
return ;
}
第二种方法:先用三分在0~90°之间找到最大值,如果最大值<y,则无解,输出-1,否则在0~t,之间二分,找到合适的角度。
代码来自: http://blog.csdn.net/hello_there/article/details/8519008 0MS
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1.0e-9;
const double PI=acos(-1.0);
const double g=9.8;
double x,y,v; double f(double t)
{
return x*tan(t)-g*x*x//(v*v*cos(t)*cos(t));
}
double two_devide(double low,double up)
{
double m;
while(up-low>=eps)
{
m=(up+low)/;
if(f(m)<=y)
low=m;
else
up=m;
}
return m;
}
double three_devide(double low,double up)
{
double m1,m2;
while(up-low>=eps)
{
m1=low+(up-low)/;
m2=up-(up-low)/;
if(f(m1)<=f(m2))
low=m1;
else
up=m2;
}
return (m1+m2)/;
}
int main()
{
int t;
double maxt;
cin>>t;
while(t--)
{
cin>>x>>y>>v;
maxt=three_devide(,PI/);
if(f(maxt)<y)
printf("-1\n");
else
printf("%.6lf\n",two_devide(,maxt));
}
return ;
}
H大意是:有n个精灵,要去同一个地方开会,他的不高兴程度=S^3*W,S,要走的距离,W,他的体重。求最小的不高兴的和。因为不确定函数的单调性,所以用三分。
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
using namespace std;
struct line
{
double bumanyi; //体重
double area; //所在的位置
}a[];
bool comp1(line x,line y)
{
return x.area<y.area;
}
int main()
{
double mid,mmid,left,right,t1,t2;
int t,i,n,w=;
scanf("%d",&t);
while(t--)
{
w++;
mid=;mmid=;
scanf("%d",&n);
for(i=;i<n;i++)
scanf("%lf %lf",&a[i].area,&a[i].bumanyi);
sort(a,a+n,comp1); //排序
left=a[].area;
right=a[n-].area; //范围
while(fabs(mid-mmid)>1e-)
{
t1=;t2=;
mid=left/+right/; //三分
mmid=mid/+right/;
for(i=;i<n;i++)
{
t1+=fabs((a[i].area-mid)*(a[i].area-mid)*(a[i].area-mid))*a[i].bumanyi;
t2+=fabs((a[i].area-mmid)*(a[i].area-mmid)*(a[i].area-mmid))*a[i].bumanyi;
}
if(t1>t2)
left=mid;
else if(t1<t2)
right=mmid;
else
break; }
printf("Case #%d: %.lf\n",w,t1);
}
return ;
}
不过这题的时限是2000MS,这个代码却用了1656,再在网上找个优化的代码。
网上的代码:531MS 其实只是把求和那用了个函数,时间就只有1/3........
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
double ab(double x)
{
return x>?x:-x;
}
struct node
{
double x;
double w;
}q[];
int n;
double cal(double xi)
{
int i;
double res=;
for(i=;i<n;i++)
{
double t=ab(q[i].x-xi);
res+=t*t*t*q[i].w;
}
return res;
}
int main()
{
int ca=,i,t;
double l,r,m,mm,ans;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=;i<n;i++)
scanf("%lf%lf",&q[i].x,&q[i].w);
l=q[].x;
r=q[n-].x;
while(l<r)
{
if(ab(r-l)<=0.001)
break;
m=(l+r)/;
mm=(m+r)/;
if(cal(m)<cal(mm))
{
ans=cal(m);
r=mm;
}
else l=m;
}
printf("Case #%d: ",ca++);
printf("%.0lf\n",ans);
}
return ;
}
第二次组队赛 二分&三分全场的更多相关文章
- HDU 2298 Toxophily 【二分+三分】
一个人站在(0,0)处射箭,箭的速度为v,问是否能够射到(x,y)处,并求最小角度. 首先需要判断在满足X=x的情况下最大高度hmax是否能够达到y,根据物理公式可得 h=vy*t-0.5*g*t*t ...
- CF 8D Two Friends 【二分+三分】
三个地点构成一个三角形. 判断一下两个人能否一起到shop然后回家,如果不能: 两个人一定在三角形内部某一点分开,假设沿着直线走,可以将问题简化. 三分从电影院出来时候的角度,在对应的直线上二分出一个 ...
- Codeforces Gym100543B 计算几何 凸包 线段树 二分/三分 卡常
原文链接https://www.cnblogs.com/zhouzhendong/p/CF-Gym100543B.html 题目传送门 - CF-Gym100543B 题意 给定一个折线图,对于每一条 ...
- Toxophily-数论以及二分三分
G - Toxophily Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u Submi ...
- CodeForces - 1059D——二分/三分
题目 题目链接 简单的说,就是作一个圆包含所有的点且与x轴相切,求圆的最小半径 方法一 分析:求最小,对半径而言肯定满足单调性,很容易想到二分.我们二分半径,然后由于固定了与X轴相切,我们对于每一个点 ...
- uva 1463 - Largest Empty Circle on a Segment(二分+三分+几何)
题目链接:uva 1463 - Largest Empty Circle on a Segment 二分半径,对于每一个半径,用三分求出线段到线段的最短距离,依据最短距离能够确定当前R下每条线段在[0 ...
- [CSP-S模拟测试]:柱状图(树状数组+二分+三分)
题目描述 $WTH$获得了一个柱状图,这个柱状图一共有$N$个柱子,最开始第$i$根柱子的高度为$x_i$,他现在要将这个柱状图排成一个屋顶的形状,屋顶的定义如下:$1.$屋顶存在一个最高的柱子,假设 ...
- HDU2899Strange fuction(二分/三分)
传送门 题目大意:求 F(x) = 6 * x^7+8*x^6+7*x^3+5*x^2-y*x (0 <= x <=100):的最小值 题解:求个导,二分导函数零点,就是原函数最小值所在的 ...
- 2020牛客寒假算法基础集训营5 B.牛牛战队的比赛地 (二分/三分)
https://ac.nowcoder.com/acm/contest/3006/B 三分做法 #include<bits/stdc++.h> #define inf 0x3f3f3f3f ...
随机推荐
- yum install mysql(转载)
linux下使用yum安装mysql 1.安装查看有没有安装过: yum list installed mysql* rpm -qa | grep mysql* 查 ...
- luogu2770 航空路线问题 网络流
题目大意: 给定一张航空图,图中顶点代表城市,边代表 2 城市间的直通航线.现要求找出一条满足下述限制条件的且途经城市最多的旅行路线.(1)从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然 ...
- 请问在C#的Winform下如何用正则表达式限制用户只能在textBox中输入18位的身份证号码。
请问在C#的Winform下如何用正则表达式限制用户只能在textBox中输入18位的身份证号码. 2013-06-18 11:07会飞的鱼儿18 | 分类:C#/.NET | 浏览101次 不能有空 ...
- css3 文本模型
我前期是一名前端开发者,经常会遇到关于文本模型的问题,很多地方我们会经常遇到这种问题.例如栏目的标题,在设计师给我们图的时候并不会考虑到标题的长度,所以我们自己开发的过程中自己注意这一点. 首先和大家 ...
- 【BZOJ1306】match循环赛
预先警告:我的做法代码量比较大 看完题目后看到数据n<=8, 不难想到这题可以写深搜来做 分析 比如说以数据: 3 3 3 3 为例子, 进行了三场比赛:AB AC BC: 我们只要搜索每场比赛 ...
- 认识JDK、JRE、JVM
JDK.JRE.JVM之间的关系: 首先看看JDK与JRE的区别与联系,如下图所示: 由图可知: JDK = JRE + Tools&Tool APIs JDK的核心是Java SE API. ...
- Combotree--别样的构建层级json字符串
1.先看效果 2.需要使用层级json格式,如: 3.先不要着急怎么去实现它,先来想想怎么用对象来描述它 4.代码 protected void Page_Load(object sender, Ev ...
- JavaScript中变量的类型
变量的类型是指变量的值所属的数据类型,可以是数值型.字符串型和布尔型等,因为JavaScript是一种弱类型的程序语言,所以可以把任意类型的数据赋值给变量. 下面是一个关于变量类型的例子.在这个例子中 ...
- Android上UDP组播无法接收数据的问题
最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,TCP连接传输文件.于是进行了一次简单的UDP组播测试,发现Android对于UDP组播接收数据的支持即极为有限. 部分代码如下 pac ...
- 【Oracle】解决oracle sqlplus 中上下左右backspace不能用
一. 解决输入 BACKSPACE 键变成 ^h 的问题 #su - oracle $stty erase ^h. 要永久生效,可以加入到用户环境配置文件.bash_profile中(vi .ba ...