AtCoderのARC    次のARCの問題へ    前のARCの問題へ

ARC054-B ムーアの法則


問題へのリンク


C#のソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static string InputPattern = "InputX";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("3.0000");
            //2.8708930019
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("0.0400");
            //0.0400000000
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("1000000000000000000.0000");
            //90.1855078128
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static double mP;

    static void Main()
    {
        List<string> InputList = GetInputList();
        mP = double.Parse(InputList[0]);

        double Result = ExecSanbuntansaku();
        Console.WriteLine(Result);
    }

    // 三分探索で極小値を求める
    static double ExecSanbuntansaku()
    {
        double L = 0;
        double R = double.MaxValue / 3;

        var PairHashSet = new HashSet<string>();
        while (L + double.Epsilon < R) {
            double C1 = (L * 2 + R) / 3;
            double C2 = (L + R * 2) / 3;

            double C1Val = CalcFunc(C1);
            double C2Val = CalcFunc(C2);

            if (C1Val < C2Val) {
                R = C2;
            }
            else {
                L = C1;
            }

            string Hash = string.Format("{0},{1}", L, R);
            if (PairHashSet.Add(Hash) == false) {
                break;
            }
        }

        var MinKouhoList = new List<double>();
        MinKouhoList.Add(CalcFunc(L));
        MinKouhoList.Add(CalcFunc(R));
        return MinKouhoList.Min();
    }

    // Pの値を引数として、コストのSumを返す
    static double CalcFunc(double pX)
    {
        return mP / Math.Pow(2, pX / 1.5) + pX;
    }
}


解説

F(0) = P
F(1) = P / (2の(1/1.5)乗) + 1
F(2) = P / (2の(2/1.5)乗) + 2
F(3) = P / (2の(2/1.5)乗) + 3

で Y=Xの一次関数
と Y=1/X の反比例のグラフ
の和のグラフに近いグラフになのと分かります。

このグラフは、下に凸で極小値を1つ持つので三分探索が使えます。