Problem:
Score: 300 points

Problem Statement

Consider an analog clock whose hour and minute hands are A and B centimeters long, respectively.

An endpoint of the hour hand and an endpoint of the minute hand are fixed at the same point, around which each hand rotates clockwise at constant angular velocity. It takes the hour and minute hands 12 hours and 1 hour to make one full rotation, respectively.

At 0 o'clock, the two hands overlap each other. H hours and M minutes later, what is the distance in centimeters between the unfixed endpoints of the hands?

Constraints

All values in input are integers.

1 \leq A, B \leq 1000

0 \leq H \leq 11

0 \leq M \leq 59

Input

Input is given from Standard Input in the following format:

A B H M

Output

Print the answer without units. Your output will be accepted when its absolute or relative error from the correct value is at most 10^{-9}.

Sample Input 1

3 4 9 0

Sample Output 1

5.00000000000000000000

The two hands will be in the positions shown in the figure below, so the answer is 5 centimeters.

Sample Input 2

3 4 10 40

Sample Output 2

4.56425719433005567605

The two hands will be in the positions shown in the figure below. Note that each hand always rotates at constant angular velocity.

Solution in Rust (1.42.0) (judge verdict: Accepted)

#![allow(unused_imports)]pub mod pcl{pub mod compat{pub mod std{pub mod ops{pub use std::ops::{Bound,RangeBounds};}}pub mod num{pub use num::{One,Zero};}}pub mod macros{#[macro_export]macro_rules!rtl{(@ lhs($($ lhs:tt)*)@ rest+=$($ rest:tt)*)=>{rtl!(@ op+=@ lhs($($ lhs)*)@ rhs()@ rest $($ rest)*)};(@ lhs($($ lhs:tt)*)@ rest-=$($ rest:tt)*)=>{rtl!(@ op-=@ lhs($($ lhs)*)@ rhs()@ rest $($ rest)*)};(@ lhs($($ lhs:tt)*)@ rest*=$($ rest:tt)*)=>{rtl!(@ op*=@ lhs($($ lhs)*)@ rhs()@ rest $($ rest)*)};(@ lhs($($ lhs:tt)*)@ rest/=$($ rest:tt)*)=>{rtl!(@ op/=@ lhs($($ lhs)*)@ rhs()@ rest $($ rest)*)};(@ lhs($($ lhs:tt)*)@ rest%=$($ rest:tt)*)=>{rtl!(@ op%=@ lhs($($ lhs)*)@ rhs()@ rest $($ rest)*)};(@ lhs($($ lhs:tt)*)@ rest $ head:tt $($ rest:tt)*)=>{rtl!(@ lhs($($ lhs)*$ head)@ rest $($ rest)*);};(@ op $ op:tt @ lhs($($ lhs:tt)*)@ rhs($($ rhs:tt)*)@ rest)=>{let __rhs=$($ rhs)*;$($ lhs)*$ op __rhs;};(@ op $ op:tt @ lhs($($ lhs:tt)*)@ rhs($($ rhs:tt)*)@ rest $ head:tt $($ rest:tt)*)=>{rtl!(@ op $ op @ lhs($($ lhs)*)@ rhs($($ rhs)*$ head)@ rest $($ rest)*);};($($ rest:tt)*)=>{rtl!(@ lhs()@ rest $($ rest)*)};}}pub mod math{pub mod modint{#[macro_use]pub mod consts{use super::ModintInnerType;pub trait ModintConst{const MOD:ModintInnerType;}#[macro_export]macro_rules!define_modint_const{($(#[doc=$ doc:expr])*pub const $ name:ident=$ value:literal;)=>{$(#[doc=$ doc])*pub enum $ name{}impl $ crate::pcl::math::modint::consts::ModintConst for $ name{const MOD:$ crate::pcl::math::modint::ModintInnerType=$ value;}};}}use num::Num;use self::consts::ModintConst;use super::super::compat::num::{One,Zero};use std::cmp::Ordering;use std::fmt;use std::hash::{Hash,Hasher};use std::iter::{Product,Sum};use std::marker::PhantomData;use std::mem;use std::ops::{Add,AddAssign,Div,DivAssign,Mul,MulAssign,Neg,Rem,RemAssign,Sub,SubAssign,};pub type ModintInnerType=i64;define_modint_const!{#[doc="1e9+7 を表す定数。"]pub const MOD17=1_000_000_007;}pub type Modint17=Modint<MOD17>;pub struct Modint<C>{value:ModintInnerType,marker:PhantomData<C>,}impl<C>Modint<C>{pub unsafe fn new_unchecked(value:ModintInnerType)->Modint<C>{#[allow(unknown_lints,renamed_and_removed_lints,redundant_field_names)]Modint{value:value,marker:PhantomData,}}pub fn inner(self)->ModintInnerType{self.value}}impl<C:ModintConst>Modint<C>{pub fn new(mut value:ModintInnerType)->Modint<C>{let modulus=C::MOD;assert_ne!(modulus,0,"MOD is 0");if value<0{let m=(-value)/modulus;value+=(m+1)*modulus;}unsafe{Modint::new_unchecked(value%modulus)}}pub fn inv(self)->Modint<C>{let mut modulus=C::MOD;let mut a=self.value;let mut u=1;let mut v=0;while modulus>0{let t=a/modulus;a-=t*modulus;u-=t*v;mem::swap(&mut a,&mut modulus);mem::swap(&mut u,&mut v);}Modint::new(u)}}impl<C:ModintConst>PartialEq for Modint<C>{fn eq(&self,other:&Self)->bool{self.inner()==other.inner()}}impl<C:ModintConst>PartialOrd for Modint<C>{fn partial_cmp(&self,other:&Self)->Option<Ordering>{self.inner().partial_cmp(&other.inner())}}impl<C:ModintConst>Eq for Modint<C>{}impl<C:ModintConst>Ord for Modint<C>{fn cmp(&self,other:&Self)->Ordering{self.inner().cmp(&other.inner())}}impl<C:ModintConst>Hash for Modint<C>{fn hash<H:Hasher>(&self,state:&mut H){self.inner().hash(state);}}impl<C>fmt::Debug for Modint<C>{fn fmt<'a>(&self,f:&mut fmt::Formatter<'a>)->fmt::Result{write!(f,"{}",self.inner())}}impl<C>Clone for Modint<C>{fn clone(&self)->Self{*self}}impl<C>Copy for Modint<C>{}impl<C:ModintConst>AddAssign for Modint<C>{fn add_assign(&mut self,rhs:Modint<C>){let modulus=C::MOD;self.value+=rhs.value;if self.value>=modulus{self.value-=modulus;}}}impl<C:ModintConst>SubAssign for Modint<C>{fn sub_assign(&mut self,rhs:Modint<C>){let modulus=C::MOD;self.value-=rhs.value;if self.value<0{self.value+=modulus;}}}impl<C:ModintConst>MulAssign for Modint<C>{fn mul_assign(&mut self,rhs:Modint<C>){let modulus=C::MOD;self.value*=rhs.value;self.value%=modulus;}}impl<C:ModintConst>DivAssign for Modint<C>{fn div_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero");}*self*=rhs.inv();}}impl<C:ModintConst>RemAssign for Modint<C>{fn rem_assign(&mut self,rhs:Modint<C>){if rhs.value==0{panic!("attempted to divide by zero.")}self.value%=rhs.value;}}impl<C:ModintConst>Neg for Modint<C>{type Output=Self;fn neg(self)->Self{Self::zero()-self}}macro_rules!impl_arith_by_assign{(impl $ traitname:ident::$ fnname:ident{use $ op:tt;})=>{impl<C:ModintConst>$ traitname for Modint<C>{type Output=Modint<C>;fn $ fnname(mut self,rhs:Modint<C>)->Modint<C>{self $ op rhs;self}}};}impl_arith_by_assign!(impl Add::add{use+=;});impl_arith_by_assign!(impl Sub::sub{use-=;});impl_arith_by_assign!(impl Mul::mul{use*=;});impl_arith_by_assign!(impl Div::div{use/=;});impl_arith_by_assign!(impl Rem::rem{use%=;});impl<C:ModintConst>One for Modint<C>{fn one()->Modint<C>{let modulus=C::MOD;assert_ne!(modulus,1,"one()is called for Modint with MOD=1");unsafe{Modint::new_unchecked(1)}}}impl<C:ModintConst>Sum for Modint<C>{fn sum<I:Iterator<Item=Modint<C>>>(iter:I)->Modint<C>{iter.fold(Modint::zero(),Add::add)}}impl<C:ModintConst>Product for Modint<C>{fn product<I:Iterator<Item=Modint<C>>>(iter:I)->Self{iter.fold(Modint::one(),Mul::mul)}}impl<C:ModintConst>Zero for Modint<C>{fn zero()->Modint<C>{unsafe{Modint::new_unchecked(0)}}fn is_zero(&self)->bool{self.inner()==0}}impl<C>fmt::Display for Modint<C>{fn fmt(&self,b:&mut fmt::Formatter)->fmt::Result{write!(b,"{}",self.inner())}}impl<C:ModintConst>Num for Modint<C>{type FromStrRadixErr=<ModintInnerType as Num>::FromStrRadixErr;fn from_str_radix(src:&str,radix:u32)->Result<Self,Self::FromStrRadixErr>{ModintInnerType::from_str_radix(src,radix).map(Modint::new)}}}pub mod sum{use super::super::compat::std::ops::RangeBounds;use super::super::traits::Group;use super::super::utils::range;pub struct CumSum<T>{psum:Vec<T>,}#[allow(unknown_lints,renamed_and_removed_lints,len_without_is_empty)]impl<T:Group+Copy>CumSum<T>{pub fn from_array<A:AsRef<[T]>>(array:A)->CumSum<T>{let array=array.as_ref();let mut psum=vec![T::id();array.len()+1];for i in 0..array.len(){let i=i+1;psum[i]=T::op(psum[i-1],array[i-1]);}#[allow(unknown_lints,renamed_and_removed_lints,redundant_field_names)]CumSum{psum:psum}}pub fn sum<R:RangeBounds<usize>>(&self,range:R)->T{let orig_len=self.psum.len()-1;let start=range::range_start(&range,0);let end=range::range_end(&range,orig_len);if end<=start{return T::id();}T::op(self.psum[end],T::inv(self.psum[start]))}pub fn len(&self)->usize{self.psum.len()-1}}pub struct CumSum2D<T>{psum:Vec<Vec<T>>,}impl<T:Group+Copy>CumSum2D<T>{pub fn from_matrix<M,A>(matrix:M)->CumSum2D<T>where M:AsRef<[A]>,A:AsRef<[T]>,{let array=matrix.as_ref();let height=array.len();if height==0{return CumSum2D{psum:vec![vec![T::id()]],};}let width=array[0].as_ref().len();let mut psum=vec![vec![T::id();width+1];height+1];for i in 0..height{let i=i+1;for j in 0..width{let j=j+1;assert_eq!(array[i-1].as_ref().len(),width,"the array's length is differ line by line");psum[i][j]=T::op(T::op(T::op(psum[i-1][j],psum[i][j-1]),T::inv(psum[i-1][j-1]),),array[i-1].as_ref()[j-1],)}}#[allow(unknown_lints,renamed_and_removed_lints,redundant_field_names)]CumSum2D{psum:psum}}pub fn sum<RY,RX>(&self,yrange:RY,xrange:RX)->T where RY:RangeBounds<usize>,RX:RangeBounds<usize>,{let orig_height=self.psum.len()-1;let orig_width=unsafe{self.psum.get_unchecked(0).len()}-1;let ystart=range::range_start(&yrange,0);let yend=range::range_end(&yrange,orig_height);let xstart=range::range_start(&xrange,0);let xend=range::range_end(&xrange,orig_width);if yend<=ystart||xend<=xstart{return T::id();}T::op(T::op(T::op(self.psum[yend][xend],self.psum[ystart][xstart]),T::inv(self.psum[ystart][xend]),),T::inv(self.psum[yend][xstart]),)}pub fn size(&self)->(usize,usize){(self.psum.len()-1,self.psum[0].len()-1)}}}pub use self::modint::{Modint,Modint17};pub use self::sum::{CumSum,CumSum2D};}pub mod structure{pub mod disjoint_sets{use std::mem::swap;pub struct DisjointSets{par:Vec<i64>,size:usize,}impl DisjointSets{pub fn new(n:usize)->DisjointSets{DisjointSets{par:vec![-1;n],size:n,}}pub fn merge(&mut self,mut x:usize,mut y:usize)->bool{let len=self.par.len();assert!(x<len,"index out of range:x is{}but len is{}",x,len);assert!(y<len,"index out of range:y is{}but len is{}",y,len);x=self.root(x);y=self.root(y);if x==y{return false;}if self.par[x]<self.par[y]{swap(&mut x,&mut y);}debug_assert!(self.par[x]<0&&self.par[y]<0,"critical error:parent has invalid value for rank");self.par[x]+=self.par[y];self.par[y]=x as i64;self.size-=1;true}pub fn in_same(&mut self,x:usize,y:usize)->bool{self.root(x)==self.root(y)}pub fn root(&mut self,x:usize)->usize{let parx=self.par[x];if parx<0{x}else{let root=self.root(parx as usize);self.par[x]=root as i64;root}}pub fn size_of(&mut self,mut x:usize)->usize{x=self.root(x);debug_assert!(self.par[x]<0,"critical error:parent has invalid value for rank");-self.par[x]as usize}pub fn size(&self)->usize{self.size}}}pub mod segment_tree{use super::super::compat::std::ops::RangeBounds;use super::super::traits::math::Monoid;use super::super::utils::range;use std::fmt;pub struct SegmentTree<T>{data:Vec<T>,lenexp2:usize,len:usize,}impl<T:fmt::Debug>fmt::Debug for SegmentTree<T>{fn fmt<'a>(&self,f:&mut fmt::Formatter<'a>)->fmt::Result{f.debug_struct("SegmentTree").field("data",&self.data).finish()}}impl<T>SegmentTree<T>where T:Monoid+Copy,{pub fn from_array<A:AsRef<[T]>>(arr:A)->SegmentTree<T>{let arr=arr.as_ref();let len=arr.len();let lenexp2=calc_lenexp2(len);let data={let mut v=vec![T::id();lenexp2*2];v[lenexp2..(lenexp2+len)].copy_from_slice(arr);v};#[allow(unknown_lints,renamed_and_removed_lints,redundant_field_names)]SegmentTree{data:data,lenexp2:lenexp2,len:len,}}pub fn update(&mut self,mut idx:usize,value:T){assert!(idx<=self.len);idx+=self.lenexp2;self.data[idx]=value;#[allow(unknown_lints,renamed_and_removed_lints,while_immutable_condition)]while{idx>>=1;idx!=0}{self.data[idx]=T::op(self.data[idx*2],self.data[idx*2+1]);}}pub fn query<R:RangeBounds<usize>>(&self,range:R)->T{let mut start=range::range_start(&range,0);let mut end=range::range_end(&range,self.len);start+=self.lenexp2;end+=self.lenexp2;let mut res1=T::id();let mut res2=T::id();while start<end{if start&1!=0{res1=T::op(res1,self.data[start]);start+=1;}if end&1!=0{end-=1;res2=T::op(self.data[end],res2);}start>>=1;end>>=1;}T::op(res1,res2)}}fn calc_lenexp2(mut len:usize)->usize{len-=1;len|=len>>1;len|=len>>2;len|=len>>4;len|=len>>8;len|=len>>16;len|=len>>32;len+1}}pub use self::disjoint_sets::DisjointSets;pub use self::segment_tree::SegmentTree;}pub mod traits{pub mod math{pub mod group{use super::monoid::Monoid;pub trait Group:Monoid{fn inv(x:Self)->Self;}use super::super::super::compat::num::Zero;use std::ops::{Add,Neg};#[derive(Debug)]pub struct Additive<T>(pub T);impl<T:Clone>Clone for Additive<T>{fn clone(&self)->Self{Additive(self.0.clone())}}impl<T:Copy>Copy for Additive<T>{}impl<T>Monoid for Additive<T>where T:Zero+Add<Output=T>,{fn op(x:Self,y:Self)->Self{Additive(x.0+y.0)}fn id()->Self{Additive(T::zero())}}impl<T>Group for Additive<T>where T:Zero+Add<Output=T>+Neg<Output=T>,{fn inv(x:Self)->Self{Additive(-x.0)}}}pub mod monoid{pub trait Monoid{fn op(x:Self,y:Self)->Self;fn id()->Self;}use super::super::utils::num::{MaxValue,MinValue};use std::cmp::Ord;use std::cmp::{max,min};use std::fmt;pub struct Min<T>(pub T);impl<T:fmt::Debug>fmt::Debug for Min<T>{fn fmt<'a>(&self,f:&mut fmt::Formatter<'a>)->fmt::Result{f.debug_tuple("Min").field(&self.0).finish()}}impl<T:Clone>Clone for Min<T>{fn clone(&self)->Self{Min(self.0.clone())}}impl<T:Copy>Copy for Min<T>{}impl<T:Ord+MaxValue>Monoid for Min<T>{fn op(x:Self,y:Self)->Self{Min(min(x.0,y.0))}fn id()->Self{Min(T::max_value())}}pub struct Max<T>(pub T);impl<T:fmt::Debug>fmt::Debug for Max<T>{fn fmt<'a>(&self,f:&mut fmt::Formatter<'a>)->fmt::Result{f.debug_tuple("Max").field(&self.0).finish()}}impl<T:Clone>Clone for Max<T>{fn clone(&self)->Self{Max(self.0.clone())}}impl<T:Copy>Copy for Max<T>{}impl<T:Ord+MinValue>Monoid for Max<T>{fn op(x:Self,y:Self)->Self{Max(max(x.0,y.0))}fn id()->Self{Max(T::min_value())}}}pub use self::group::Group;pub use self::monoid::Monoid;}pub mod utils{pub mod num{pub trait MaxValue{fn max_value()->Self;}pub trait MinValue{fn min_value()->Self;}macro_rules!impl_minmax_value_for_primitives{($($ ty:tt)*)=>{$(impl MaxValue for $ ty{fn max_value()->$ ty{::std::$ ty::MAX}}impl MinValue for $ ty{fn min_value()->$ ty{::std::$ ty::MIN}})*};}impl_minmax_value_for_primitives!{u8 u16 u32 u64 usize i8 i16 i32 i64 isize}}}pub use self::math::*;}pub mod utils{pub mod range{use std::cmp;use super::super::compat::std::ops::{Bound,RangeBounds};pub fn range_start<R:RangeBounds<usize>>(range:&R,min:usize)->usize{let start=match range.start_bound(){Bound::Included(&x)=>x,Bound::Excluded(&x)=>x+1,Bound::Unbounded=>0,};cmp::max(start,min)}pub fn range_end<R:RangeBounds<usize>>(range:&R,max:usize)->usize{let end=match range.end_bound(){Bound::Included(&x)=>x+1,Bound::Excluded(&x)=>x,Bound::Unbounded=>max,};cmp::min(end,max)}}}}
use itertools::Itertools as _;
use proconio::input;
use std::f64::consts::PI;
fn main() {
    input! { a : f64 , b : f64 , h : f64 , m : f64 , }
    let ta = 2.0 * PI * (h * 60.0 + m) / (12.0 * 60.0);
    let tb = 2.0 * PI * m / 60.0;
    let angle = (ta - tb).abs();
    let len = a * a + b * b - 2.0 * a * b * angle.cos();
    println!("{:.9}", len.sqrt());
}