#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;
double comp(double x)
{
return ( 8*pow(x,4) + 7*pow(x,3) + 2*pow(x,2) + 3*x + 6 );
}
int main()
{
int t;
double Y;
scanf("%d",&t);
while( t-- && scanf("%lf",&Y) )
{
if( comp(0.0) > Y || comp(100.0) < Y)
{
printf("No solution!\n");
continue;
}
double l = 0.0, r = 100.0 ;
while( r - l > 1e-6)
{
double mid = ( l + r ) / 2.0;
double ret = comp( mid );
if( ret < Y)
l = mid + 1e-6;
else
r = mid - 1e-6;
}
printf("%.4lf\n", (l + r) / 2.0);
}
return 0;
}
Strange fuction
/*
求函数的最小值,首先求导的导函数为:G(x) = 42 * x^6+48*x^5+21*x^2+10*x-y (0 <= x <=100)
分析导函数的,导函数为一个单调递增的函数。如果导函数的最大值小于0,
那么原函数在区间内单调递减。
即F(100)最小;如果但函数的最小值大于0,那么原函数在区间内单调递增,即F(0)最小。
如果导函数既有正又有负
又由于导函数是单增函数,所以必有先负后正,即原函数必有先减后增的性质。
求出导函数的零点就是原函数的最小值点。
求导函数最小值方法是2分法.
*/
#include<iostream>
#include <cstdio>
#include <cmath>
double Y;
double cpt( double x ) //导函数
{
return ( 42 * pow(x,6) + 48 * pow(x,5) + 21*pow(x,2) + 10*x );
}
double ret( double x ) //求结果
{
return ( 6 * pow(x,7)+8*pow(x,6)+7*pow(x,3)+5*x*x-Y*x );
}
int main()
{
int t;
double s;
scanf ("%d",&t);
while( t-- && scanf("%lf",&Y) )
{
double l = 0.0, r = 100.0,mid;
while( r - l > 1e-8 )
{
mid = ( l + r ) / 2.0;
s = cpt( mid );
if ( s > Y )
r = mid - 1e-8;
else
l = mid + 1e-8;
}
mid = ( l + r ) / 2.0;
printf("%.4lf\n", ret(mid) );
}
return 0;
}
Pie
/*
题目大意是要办生日Party,有n个馅饼,有f个朋友,接下来是n个馅饼的半径。然后是分馅饼了,
注意咯自己也要,大家都要一样大,形状没什么要求,但都要是一整块的那种,
也就是说不能从两个饼中各割一小块来凑一块,像面积为10的和6的两块饼
(饼的厚度是1,所以面积和体积相等),
如果每人分到面积为5,则10分两块,6切成5,够分3个人,如果每人6,则只能分两个了!
题目要求我们分到的饼尽可能的大!
只要注意精度问题就可以了,一般WA 都是精度问题
运用2分搜索:
首先用总饼的体积除以总人数,得到每个人最大可以得到的V,
但是每个人手中不能有两片或多片拼成的一块饼,
最多只能有一片分割过得饼。用2分搜索时,把0设为left,把V 设为right。mid=(left+right)/2;
搜索条件是:以mid为标志,如果每块饼都可以分割出一个mid,那么返回true,
说明每个人可以得到的饼的体积可以
大于等于mid;如果不能分出这么多的mid,那么返回false,
说明每个人可以得到饼的体积小于等于mid。
(1)精度为:0.000001
(2) pi 用反余弦求出,精度更高。
*/
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
double pi = acos(-1.0);
int F,N;
double V[10001];
bool test(double x)
{
int num=0;
for(int i = 0; i < N;i++)
{
num += int(V[i]/x);
}
if(num>=F)
return true;
else return false;
}
int main()
{
int t,r;
double v,max,left,right,mid;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&N,&F);
F = F+1;
for(int i = 0; i < N; i++)
{
scanf("%d",&r);
V[i] = pi*r*r;
v += V[i];
}
max = v/F;
left = 0.0;
right = max;
while((right-left)>1e-6)//注意这里的精度问题。
{
mid = (left+right)/2;
if(test(mid))
left = mid;
else right = mid;
}
printf("%.4f\n",mid);
}
return 0;
}
Can you find it?
#include<iostream>
#include<algorithm>
using namespace std;
int L, N, M, s, x, flag, k;
int a[501], b[501], c[501], sum[250001];
int Judge(int p)
{
int l, r, m;
l=0;
r=k-1;
if(sum[l]==p||sum[r]==p)
{
flag=1;
return 1;
}
while(l<=r)
{
m=(l+r)/2;
if(sum[m]==p)
{
flag=1;
return 1;
}
else if(sum[m]>p)
r=m-1;
else if(sum[m]<p)
l=m+1;
}
return 0;
}
int main()
{
int i, j, t=0;
while(cin>>L>>N>>M)
{
printf("Case %d:\n", ++t);
for(i=0;i<L;i++)
scanf("%d",&a[i]);
for(i=0;i<N;i++)
scanf("%d",&b[i]);
for(i=0, k=0;i<L;i++)
{
for(j=0;j<N;j++)
sum[k++]=a[i]+b[j];
}
sort(sum,sum+k);
for(i=0;i<M;i++)
scanf("%d",&c[i]);
cin>>s;
while(s--)
{
cin>>x;
flag=0;
for(i=0;i<M;i++)
{
if(x-c[i]>sum[k-1])
continue;
if(Judge(x-c[i]))
break;
}
if(flag)
printf("YES\n");
else
printf("NO\n");
}
}
return 0;
}
Toxophily
/*
用公式,根据正交分解坐标系,得出方程的通式。
想 x^2*g/(2*v^2)*tan^2(?) - x*tan(?) +y + x^2*g/(2*v^2) = 0;
即:a = g*pow(x,2)/(2*pow(v,2));
b = -x;
c = y + g*pow(x,2)/(2*pow(v,2));
根据求根公式求出根。
注意讨论:
(1) x==0&&y==0时,? = 0;
(2) x==0&&y>0时,?=90;
(3) 方程无解时 ?=-1;
(4) 方程的解为负数时,?=-1;(0<=?<=90)。
*/
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
int main()
{
int t;
double a,b,c,angle,z;
double x,y,v,g = 9.8,T,ans1,ans2;
scanf("%d",&t);
while(t--)
{
scanf("%lf%lf%lf",&x,&y,&v);
if(x==0&&y==0)
printf("0\n");
else if(x==0&&y>0)
printf("90\n");
else
{
a = g*pow(x,2)/(2*pow(v,2));
b = -x;
c = y+a;
T = pow(b,2) - 4*a*c;
angle = 0;
if(T<0)
printf("-1\n");
else
{
ans1 = ((-b)+pow(T,1.0/2))/(2*a);
ans2 = ((-b)-pow(T,1.0/2))/(2*a);
if(ans1>=0) angle = atan(ans1);
if(ans2>=0)
{
z = atan(ans2);
if(z<angle) angle = z;
printf("%.6f\n",angle);
}
if(ans1<0&&ans2<0)
printf("-1\n");
}
}
}
return 0;
}
Turn the corner
/*
思路:显然为了让车子能顺利通过弯道,我们应该使车子擦着左边那个墙角走,
在转弯的过程中,车子的右下端(点p)露在最外面,所以我们只需判断点p能否顺利通过就行。
下面就是数学知识了,我们可以建立p的横坐标关于θ的函数,这个画个图可以算出来,
现在给出其函数表达式:f(θ)=l*cos(θ)-(x*cos(θ)-d)/sin(θ).
f(θ)在区间(0,π/2)上先增后减,所以我们需要求出f(θ)的最大值,
若f(θ)<=y则车子可以通过,否则不能通过。
对于这样的一个先增后减的函数,我们可以用三分求出其极大值。
*/
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double PI=acos(-1.0);
const double eps=1.0e-6;
double x,y,l,d;
double f(double t)//计算右下方顶点的横坐标(离第一条竖直线的距离)
{
return l*cos(t)-(x*cos(t)-d)/sin(t);
}
int main()
{
double low,up,mid1,mid2;
while(cin>>x>>y>>l>>d)
{
low=0;
up=PI/2;
while(up-low>=eps)
{
mid1=low+(up-low)/3;
mid2=up-(up-low)/3;
if(f(mid1)<=f(mid2))
low=mid1;
else
up=mid2;
}
if(f(mid1)<=y)
printf("yes\n");
else
printf("no\n");
}
return 0;
}
Cable master
#include<iostream>
#include<iomanip>
using namespace std;
double a[10005];
int N,K;
int check(double x)
{
int i,sum=0;
for(i=0;i<N;i++)
sum+=(int)(a[i]/x);
if(sum<K)
return 0;
return 1;
}
int main()
{
int i;
double left,right,mid,max;
while(scanf("%d%d",&N,&K)!=EOF)
{
if(N==0&&K==0) break;
max=0;
for(i=0;i<N;i++)
{
scanf("%lf",&a[i]);
if(a[i]>max)
max=a[i];
}
left=0;
right=max;
while(right-left>0.001)
{
mid=(right+left)/2;
if(check(mid))
left=mid;
else
right=mid;
}
printf("%.2lf\n",mid);
}
return 0;
}
Dome of Circus
/*
这个题虽然是三维的,但是可以很容易的转化到二维去
。来看X-Z这个平面,我们将所有的点进行圆周映射,然后将所有的点都投影到
X-Z平面的的第一象限去,然后问题就转化成了在X-Z平面上找到一条斜率为负
的直线L,L和X正方向、Z正方向围成的三角形包含所有点,如果假设L和X轴的
交点为R,和Z轴焦点为H,要求pi*H*R^2的值最小。
L这条线必定和某一
个给定的点擦边,也就是经过那个点,我们假设它经过P(a, b), 并且L的斜率
为K(K < 0),那么L的方程就可以表示为 L: y = K * (x - a) + b,则H和R就
可以利用这个方程表示出来:
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#define eps 1e-7
#include <set>
#include <vector>
using namespace std;
struct point{
double x,y,z;
point(){}
point(double a, double b, double c){x = a, y = b, z = c;}
}p[11111];
int n,T;
double a,b,c;
double cal(double r){
double h ,Max = 0;
for(int i = 0; i < n; i ++){
h = p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y));
Max = max(h,Max);
}
return r * r * Max;
}
void thi(double &r, double &h){
double low = 0.0, high = 10000;
double m1,m2;
while(low + eps < high){
m1 = (low + high) / 2.0;
m2 = (m1 + high) / 2.0;
if(cal(m1) <= cal(m2)) high = m2;
else {
low = m1;
}
}
r = low;
h = -1;
for(int i = 0; i < n; i ++){
h = max(h,p[i].z * r / (r - sqrt(p[i].x * p[i].x + p[i].y * p[i].y)) );
}
}
int main(){
scanf("%d",&T);
while(T --){
scanf("%d",&n);
for(int i = 0; i < n; i ++){
scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].z);
}
double r,h;
thi(r,h);
printf("%.3f %.3f\n",h,r);
}
return 0;
}