競技プログラミングの鉄則
次の問題へ
前の問題へ
A57 Doubling
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("7 4");
WillReturn.Add("2 4 1 7 6 5 3");
WillReturn.Add("1 1");
WillReturn.Add("1 5");
WillReturn.Add("2 13");
WillReturn.Add("5 999999999");
//2
//1
//3
//6
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
struct XYInfoDef
{
internal long X;
internal long Y;
}
static List<XYInfoDef> mXYInfoList = new List<XYInfoDef>();
static void Main()
{
List<string> InputList = GetInputList();
long[] AArr = InputList[1].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long UB = AArr.GetUpperBound(0);
for (long I = 0; I <= UB; I++) {
AArr[I]--; // 0オリジンに変更
}
long[] wkArr = { };
Action<string> SplitAct = pStr =>
wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();
foreach (string EachStr in InputList.Skip(2)) {
SplitAct(EachStr);
XYInfoDef WillAdd;
WillAdd.X = wkArr[0] - 1; // 0オリジンに変更
WillAdd.Y = wkArr[1];
mXYInfoList.Add(WillAdd);
}
// アリごとの現在位置[2べきの値]なDictの配列
var DoublingDictArr = new Dictionary<long, long>[UB + 1];
for (long I = 0; I <= UB; I++) {
DoublingDictArr[I] = new Dictionary<long, long>();
}
// 1日後の位置を設定
for (long I = 0; I <= UB; I++) {
DoublingDictArr[I][1] = AArr[I];
}
// 2べき日後の位置を設定
long MaxY = mXYInfoList.Max(pX => pX.Y);
long Beki2 = 2;
while (Beki2 <= MaxY) {
long Div2 = Beki2 / 2;
for (long I = 0; I <= UB; I++) {
long Div2Pos = DoublingDictArr[I][Div2];
long GoalPos = DoublingDictArr[Div2Pos][Div2];
DoublingDictArr[I][Beki2] = GoalPos;
}
Beki2 *= 2;
}
// クエリに回答
var sb = new System.Text.StringBuilder();
foreach (XYInfoDef EachXYInfo in mXYInfoList) {
long CurrPos = EachXYInfo.X;
long RestDay = EachXYInfo.Y;
while (RestDay > 0) {
long MaxBeki2 = DeriveMaxBeki2(RestDay);
CurrPos = DoublingDictArr[CurrPos][MaxBeki2];
RestDay -= MaxBeki2;
}
sb.Append(CurrPos + 1); // 1オリジンに戻す
sb.AppendLine();
}
Console.Write(sb.ToString());
}
// 引数の数値以下で、最大の2べきを返す
static long DeriveMaxBeki2(long pTarget)
{
long WillReturn = 1;
for (long I = 1; I < long.MaxValue; I *= 2) {
if (I <= pTarget) {
WillReturn = I;
}
else {
break;
}
}
return WillReturn;
}
}
解説
ダブリングで解いてます。