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つ持つので三分探索が使えます。