15 国庆本校脑残题题解
Hdu 2289 à Cup
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2289
题意: 给你一个杯子(圆台状的),告诉你下底半径、上底半径、高度和里面装的水的体积,然后问你水的高度。
算法:二分
思路:对水的高度进行二分,根据比例求水的体积,与题目给定的体积进行比较。
Hdu 3400 à Line belt
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3400
题意:给你两条线ab和cd,告诉你这四个点的坐标,然后ab上的移动速度为p,cd上的移动速度是q,两条线之外的地方移动速度为r,然后问你从a到d最短时间需要多少?
算法:三分
思路:假设在ab线上移动的距离x,在cd线上的移动距离y,然后时间就等于 x/p + y/q + 两点间距离/r ,做法用三分找x,然后将x和找到的点传递下去三分找y,期间两次都是找极小值。
1 #include<stdio.h> 2 #include<conio.h> 3 #include<math.h> 4 #define EPS 0.00000001 5 typedef struct node 6 { 7 double x,y; 8 }Node; 9 double lab,lcd; 10 Node funa(Node a,Node b,double x) // a -> b 11 { 12 Node tmp; 13 if(lab==0) 14 { 15 return a; 16 } 17 double sab=(b.y-a.y)/lab; 18 double cab=(b.x-a.x)/lab; 19 tmp.y=x*sab+a.y; 20 tmp.x=x*cab+a.x; 21 return tmp; 22 } 23 Node fund(Node c,Node d,double x) // d -> c 24 { 25 Node tmp; 26 if(lcd==0) 27 { 28 return c; 29 } 30 double scd=(c.y-d.y)/lcd; 31 double ccd=(c.x-d.x)/lcd; 32 tmp.y=d.y+x*scd; 33 tmp.x=d.x+x*ccd; 34 return tmp; 35 } 36 double funab(Node a,Node b) 37 { 38 return sqrt((b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x)); 39 } 40 int t,p,q,w; 41 double solve(Node A,Node B,double i,double j) 42 { 43 double ans=funab(A,B)/w; 44 ans+=i/p; 45 ans+=j/q; 46 return ans; 47 } 48 Node a,b,c,d; 49 double fun(Node A,double x,double y) 50 { 51 Node B=fund(c,d,y); 52 return solve(A,B,x,y); 53 } 54 double san(Node A,double x,double l,double r) 55 { 56 double mid,mmid; 57 double fm,fmm; 58 while(l+EPS<r) 59 { 60 mid=(l+r)/2; 61 mmid=(r+mid)/2; 62 fm=fun(A,x,mid); 63 fmm=fun(A,x,mmid); 64 // 以求极小值为例 65 if(fm>=fmm) l=mid; 66 else r=mmid; 67 } 68 fm=fun(A,x,l); 69 return fm; 70 } 71 double f(double x) 72 { 73 Node A=funa(a,b,x); 74 return san(A,x,0,lcd); 75 } 76 double san_f(double l,double r) 77 { 78 double mid,mmid; 79 double fm,fmm; 80 while(l+EPS<r) 81 { 82 mid=(l+r)/2; 83 mmid=(r+mid)/2; 84 fm=f(mid); 85 fmm=f(mmid); 86 // 以求极小值为例 87 if(fm>=fmm) l=mid; 88 else r=mmid; 89 } 90 fm=f(l); 91 return fm; 92 } 93 int main() 94 { 95 scanf("%d",&t); 96 while(t--) 97 { 98 scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y); 99 scanf("%lf%lf%lf%lf",&c.x,&c.y,&d.x,&d.y); 100 scanf("%d%d%d",&p,&q,&w); 101 lab=funab(a,b); 102 lcd=funab(c,d); 103 double mt=san_f(0,lab); 104 printf("%.2lf\n",mt); 105 } 106 return 0; 107 }
下面两道水题,不做无妨。
题目:n ! % ( k ^ i ) == 0
题意:给你n和k,求最大的i 使得 n!% ( k ^ i ) == 0 ; 数据范围非常大
算法:素因子分解
思路:先将k分解,那么可以得到 k = p1 ^ a1 + p2 ^ a2 + p3 ^ a3 + ….. –> 那么k^i里面就有i倍的这些素因子。那么可以算出n!里面这些素因子的个数,然后把这个结果除以k里面相应素因子的个数,找出最小的那个,就是答案。
题目: 略
题意:有一个n*n的棋盘,A站在(1,1),B站在(1,n),然后轮流行动,一次可以上下左右斜着走一步,然后走过的地方不能进入,不能走或被对方踩到自己算输。
算法:博弈论
思路:两人之间隔单数列,那么先走的必输,隔偶数列,先走的人必赢,因为单隔1列的时候,先走的人要么前进一列,然后乖乖受死,要么上升一格,这时,对方可以跟着你的动作,也就是说情况保持不变,当你不能竖着走的时候,你就输了。如果隔两列,那么先走的人可以前进一列,进入第一种情况。隔更多列时类似。。。