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 C# (.NET Core 3.1.201) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
 
public class ABC168_C
{
 
    public static void Main()
    {
        InLineArg(out int[] ints);
        double ra = ints[2] * 30 + ints[3] * 0.5;
        double rb = ints[3] * 6;
        double r = ra - rb;
        if (r < 0) r *= -1;
        result = Math.Sqrt(ints[0] * ints[0] + ints[1] * ints[1] - 2 * ints[0] * ints[1] * Math.Cos(r * Math.PI / 180));
        OutResult();
    }
 
    /* Template */
    private static object[] nullobj = null;
    public static int len = -1;
    public static int count = -1;
    public static double result = 0;
    public static string line = "";
 
    //文字コード変換
    public static int ConvertInt(char c)
    {
        return c;
    }
 
    //配列入力:1入力
    public static A[] InArgs<A>(int count)
    {
        InArgs(count, out A[] var, out nullobj, out nullobj, 1);
        return var;
    }
 
    //配列入力:1入力
    public static void InArgs<A>(int count, out A[] var)
    {
        InArgs(count, out var, out nullobj, out nullobj, 1);
    }
 
    //配列入力:2入力
    public static void InArgs<A, B>(int count, out A[] var1, out B[] var2)
    {
        InArgs(count, out var1, out var2, out nullobj, 2);
    }
 
    //配列入力:3入力
    public static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3)
    {
        InArgs(count, out var1, out var2, out var3, 3);
    }
 
    //配列入力:内部処理
    private static void InArgs<A, B, C>(int count, out A[] var1, out B[] var2, out C[] var3, int ci)
    {
        var1 = new A[count];
        var2 = new B[count];
        var3 = new C[count];
        for (int i = 0; i < count; i++)
        {
            InLine(out var1[i], out var2[i], out var3[i], ci);
        }
    }
 
    //入力:1入力
    public static A InLine<A>()
    {
        InLine(out A var);
        return var;
    }
 
    //入力:1入力
    public static void InLine<A>(out A var)
    {
        InLine(out var, out nullobj, out nullobj, 1);
    }
 
    //入力:2入力
    public static void InLine<A, B>(out A var1, out B var2)
    {
        InLine(out var1, out var2, out nullobj, 2);
    }
 
    //入力:3入力
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3)
    {
        InLine(out var1, out var2, out var3, 3);
    }
 
    //入力:内部処理
    public static void InLine<A, B, C>(out A var1, out B var2, out C var3, int c)
    {
        var2 = default;
        var3 = default;
        object[] o = new object[c];
        Type[] t = new Type[] { typeof(A), typeof(B), typeof(C) };
 
        var line = Console.ReadLine();
        string[] s;
        if (o.Length == 1) s = new string[1] { line };
        else s = line.Split(' ');
        for (int i = 0; i < s.Length; i++)
        {
            if (typeof(int) == t[i]) o[i] = int.Parse(s[i]);
            else if (typeof(long) == t[i]) o[i] = long.Parse(s[i]);
            else if (typeof(double) == t[i]) o[i] = double.Parse(s[i]);
            else o[i] = s[i];
        }
        var1 = (A)o[0];
        if (c == 2) var2 = (B)o[1];
        if (c == 3) var3 = (C)o[2];
    }
 
    //入力:1行配列
    public static A[] InLineArg<A>()
    {
        InLineArg(out A[] var);
        return var;
    }
 
    //入力:1行配列
    public static void InLineArg<A>(out A[] arg)
    {
        object obj = null;
        Type t = typeof(A);
        string[] line = Console.ReadLine().Split(' ');
        if (typeof(int) == t) obj = line.Select(int.Parse).ToArray();
        else if (typeof(long) == t) obj = line.Select(long.Parse).ToArray();
        else if (typeof(double) == t) obj = line.Select(double.Parse).ToArray();
        else obj = line;
        arg = (A[])obj;
    }
 
    //文字列結合
    public static string JoinString(object obj, string sep)
    {
        return obj.GetType().IsArray ?
            string.Join(sep, ((IEnumerable<object>)obj).Select(i => i.ToString()).ToArray()) : obj.ToString();
    }
 
    //出力
    public static void Out(object o)
    {
        Console.WriteLine(o);
    }
 
    //出力:変数result
    public static void OutResult()
    {
        Console.WriteLine(result);
    }
 
    //出力:Yes
    public static void OutYes()
    {
        Console.WriteLine("Yes");
    }
 
    //出力:No
    public static void OutNo()
    {
        Console.WriteLine("No");
    }
 
    //出力:YES
    public static void OutYES()
    {
        Console.WriteLine("YES");
    }
 
    //出力:NO
    public static void OutNO()
    {
        Console.WriteLine("NO");
    }
 
    //辞書生成
    private static Dictionary<A, B> PutDict<A, B>(A[] key, B[] value)
    {
        if (key.Length != value.Length) return null;
        var dic = new Dictionary<A, B>();
        for (int i = 0; i < Math.Min(key.Length, value.Length); i++)
        {
            if (!dic.ContainsKey(key[i])) dic.Add(key[i], value[i]);
            else dic[key[i]] = value[i];
        }
        return dic;
    }
 
    //最大
    public static int[] Max(int[] array, int count)
    {
        int[] result = new int[count];
        for (int c = 0; c < count; c++)
        {
            int max = -1;
            int plus = Vector<int>.Count;
            var vmax = new Vector<int>(max);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Max(vmax, new Vector<int>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (max < vmax[i]) max = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (max < array[i]) max = array[i];
            }
 
            result[c] = max;
            if (c != count - 1)
            {
                var list = new List<int>(array);
                list.Remove(max);
                array = list.ToArray();
            }
        }
        return result;
    }
 
    //最小
    public static int[] Min(int[] array, int count)
    {
        int[] result = new int[count];
        for (int c = 0; c < count; c++)
        {
            int min = int.MaxValue;
            int plus = Vector<int>.Count;
            var vmax = new Vector<int>(min);
            for (int i = 0; i < array.Length - plus; i += plus)
            {
                vmax = Vector.Min(vmax, new Vector<int>(array, i));
            }
            for (int i = 0; i < plus; i++)
            {
                if (min > vmax[i]) min = vmax[i];
            }
            for (int i = array.Length - plus; i < array.Length; i++)
            {
                if (i < 0) i = 0;
                if (min > array[i]) min = array[i];
            }
 
            result[c] = min;
            if (c != count - 1)
            {
                var list = new List<int>(array);
                list.Remove(min);
                array = list.ToArray();
            }
        }
        return result;
    }
 
    //公約数
    public static int[] CommonDivisor(int num)
    {
        return CommonDivisor((double)num).Select(i => (int)i).ToArray();
    }
 
    public static double[] CommonDivisor(double num)
    {
        double l = 2, n = num;
        double[] result = new double[0];
 
        while (l * l <= num)
        {
            if (n % l == 0)
            {
                n /= l;
                Array.Resize(ref result, result.Length + 1);
                result[^1] = l;
            }
            else l++;
        }
        if (n != 1)
        {
            Array.Resize(ref result, result.Length + 1);
            result[^1] = n;
        }
        return result;
    }
 
    //大小比較
    public static bool Compare(bool lequal, double a, double x, double b, bool requal)
    {
        if (a <= x && x <= b)
        {
            if ((!lequal && x == a) || (!requal && x == b)) return false;
            else return true;
        }
        return false;
    }
 
    //互いに素
    public static bool IsRelativelyPrime(double a, double b)
    {
        return a > 1 && b > 1 ? CommonDivisor(a).Intersect(CommonDivisor(b)).ToArray().Length == 0 : false;
    }
 
    //素数判定
    public static bool IsPrimeNumber(int num)
    {
        if (num < 2) return false;
        else if (num == 2) return true;
        else if (num % 2 == 0) return false;
 
        double sqrtNum = Math.Sqrt(num);
        for (int i = 3; i <= sqrtNum; i += 2)
        {
            if (num % i == 0) return false;
        }
        return true;
    }
 
    //最大公約数
    public static int GCD(int a, int b)
    {
        return (int)GCD((double)a, b);
    }
 
    public static double GCD(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        Dictionary<double, int> dic1 = new Dictionary<double, int>(), dic2 = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic1.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic1.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic1.ContainsKey(n)) dic2[n] = Math.Max(count, dic1[n]);
        foreach (double l in dic2.Keys)
        {
            result *= Math.Pow(l, dic2[l]);
        }
        return result;
    }
 
    //最小公倍数
    public static double LCM(double a, double b)
    {
        double[] acd = CommonDivisor(a).ToArray(), bcd = CommonDivisor(b).ToArray();
        var dic = new Dictionary<double, int>();
        int count = 0;
        double n = 0, result = 1;
        for (int i = 0; i < acd.Length; i++)
        {
            if (n == acd[i]) count++;
            else
            {
                if (n != 0) dic.Add(n, count);
                n = acd[i];
                count = 1;
            }
        }
        dic.Add(n, count);
        n = 0;
        count = 0;
        for (int i = 0; i < bcd.Length; i++)
        {
            if (n == bcd[i]) count++;
            else
            {
                if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
                else if (n != 0) dic.Add(n, count);
                n = bcd[i];
                count = 1;
            }
        }
        if (dic.ContainsKey(n)) dic[n] = Math.Max(count, dic[n]);
        else dic.Add(n, count);
        foreach (double l in dic.Keys)
            result *= (double)Math.Pow(l, dic[l]);
        return result;
    }
 
    //組合せ数(nCr)
    public static double Combination(int n, int r)
    {
        if (n / 2 < r) r = n - r;
        return TotalPower(n, r + 1) / TotalPower(n - r);
    }
 
    //組合せ数総和(Σ(k=1,n,nCk))
    public static double CombinationSum(int n)
    {
        return Math.Pow(2, n);
    }
 
    //重複組合せ数(nHr)
    public static double RepetitionCombination(int n, int r)
    {
        return Combination(n + r - 1, r);
    }
 
    //重複組合せ数総和(Σ(k=1,n,nHk))
    public static double RepetitionCombinationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionCombination(n, i);
        }
        return result;
    }
 
    //順列数(nPr)
    public static double Permutation(int n, int r)
    {
        return TotalPower(n, r + 1);
    }
 
    //順列数総和(Σ(k=1,n,nPk))
    public static double PermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += Permutation(n, i);
        }
        return result;
    }
 
    //円順列数
    public static double CircularPermutation(int n)
    {
        return TotalPower(n - 1);
    }
 
    //円順列数総和
    public static double CircularPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += CircularPermutation(i);
        }
        return result;
    }
 
 
 
    //数珠順列数
    public static double NecklacePermutation(int n)
    {
        return CircularPermutation(n - 1) / 2;
    }
 
    //数珠順列数総和
    public static double NecklacePermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += NecklacePermutation(i);
        }
        return result;
    }
 
    //重複順列数(nΠr)
    public static double RepetitionPermutation(int n, int r)
    {
        return Math.Pow(n, r);
    }
 
    //重複順列数総和(Σ(k=1,n,nΠk))
    public static double RepetitionPermutationSum(int n)
    {
        double result = 0;
        for (int i = 1; i <= n; i++)
        {
            result += RepetitionPermutation(n, i);
        }
        return result;
    }
 
    //総乗
    public static double TotalPower(int max)
    {
        return TotalPower(max, 1);
    }
 
    public static double TotalPower(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result *= i;
        return result;
    }
 
    public static double TotalPower(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result *= i;
        return result;
    }
 
    //総和
    public static double TotalSum(int max)
    {
        return TotalSum(max, 1);
    }
 
    public static double TotalSum(int max, int min)
    {
        double result = 1;
        for (int i = min; i <= max; i++) result += i;
        return result;
    }
 
    public static double TotalSum(int[] ints)
    {
        double result = 1;
        foreach (int i in ints) result += i;
        return result;
    }
}