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番目の項が
何群目に所属するかは、二分探索で求めることができます。

何群目かが分かれば
群の番目を求めることができるので
群の番目から解を求めることができます。