AtCoderのPAST
次のPASTの問題へ
前のPASTの問題へ
第11回PAST E 変わった数列
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("10");
//4
}
else if (InputPattern == "Input2") {
WillReturn.Add("1");
//1
}
else if (InputPattern == "Input3") {
WillReturn.Add("123456789012345678");
//268452372
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long N = long.Parse(InputList[0]);
long Result = Solve(N);
Console.WriteLine(Result);
}
static long Solve(long pVal)
{
if (pVal == 1) {
return 1;
}
long L = 1;
long R = long.MaxValue;
while (L + 1 < R) {
long Mid = long.MaxValue / 2;
if (R < long.MaxValue) {
Mid = (L + R) / 2;
}
if (WillOverProd(Mid, Mid, long.MaxValue)) {
R = Mid;
continue;
}
if (Mid * Mid < pVal) {
L = Mid;
}
else {
R = Mid;
}
}
long CurrI = R;
long Rest = pVal - (CurrI - 1) * (CurrI - 1);
long Result;
if (Rest > CurrI) {
Result = Rest - CurrI + 1;
}
else {
Result = CurrI - (Rest - 1);
}
return Result;
}
// 2正数の掛け算が、Limitを超えるかを返す
static bool WillOverProd(long pA, long pB, long pLimit)
{
return pA > pLimit / pB;
}
}
解説
群数列で考えます。
1 ■ 2 1 2 ■ 3 2 1 2 3 ■ 4 3 2 1 2 3 4 ■
最初に
N番目の項が
何群目に所属するかを求めます。
これは、群ごとの項数が
1,3,5,7
で累積和を求めると
1,4,9,16
平方数だと分かるので、
N番目の項が
何群目に所属するかは、二分探索で求めることができます。
何群目かが分かれば
群の番目を求めることができるので
群の番目から解を求めることができます。