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
",mt);
105   }
106   return 0;
107 }
AC代码

下面两道水题,不做无妨。

题目: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列的时候,先走的人要么前进一列,然后乖乖受死,要么上升一格,这时,对方可以跟着你的动作,也就是说情况保持不变,当你不能竖着走的时候,你就输了。如果隔两列,那么先走的人可以前进一列,进入第一种情况。隔更多列时类似。。。

原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/4858727.html