AtCoderのABC    次のABCの問題へ    前のABCの問題へ

ABC250-D 250-like Number


問題へのリンク


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("250");
            //2
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("1");
            //0
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("123456789012345");
            //226863
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static long mN;

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

        long Jyougen = 1;
        while (Jyougen * Jyougen * Jyougen < mN) {
            Jyougen++;
        }
        Eratosthenes(Jyougen);

        long Answer = 0;
        for (long I = 1; I <= mSosuuArr.GetUpperBound(0); I++) {
            long Sanjyou = mSosuuArr[I] * mSosuuArr[I] * mSosuuArr[I];
            if (Sanjyou >= mN) break;

            long Result = ExecNibunhou(Sanjyou, I - 1);
            Answer += Result + 1;
        }
        Console.WriteLine(Answer);
    }

    static long ExecNibunhou(long pSanjyou, long pR)
    {
        long L = 0;
        long R = pR;

        if (pSanjyou * 2 > mN) {
            return -1;
        }

        if ((decimal)pSanjyou * mSosuuArr[pR] <= mN) {
            return pR;
        }

        while (L + 1 < R) {
            long Mid = (L + R) / 2;

            if ((decimal)pSanjyou * mSosuuArr[Mid] > mN) {
                R = Mid;
            }
            else {
                L = Mid;
            }
        }
        return L;
    }

    static long[] mSosuuArr;

    // エラトステネスの篩
    static void Eratosthenes(long pJyougen)
    {
        bool[] IsSosuuArr = new bool[pJyougen + 1];
        for (int I = 2; I <= IsSosuuArr.GetUpperBound(0); I++) {
            IsSosuuArr[I] = true;
        }
        for (int I = 2; I * I <= IsSosuuArr.GetUpperBound(0); I++) {
            if (IsSosuuArr[I]) {
                for (int J = I * 2; J <= IsSosuuArr.GetUpperBound(0); J += I) {
                    IsSosuuArr[J] = false;
                }
            }
        }

        var SosuuList = new List<long>();
        for (int I = 2; I <= IsSosuuArr.GetUpperBound(0); I++) {
            if (IsSosuuArr[I]) SosuuList.Add(I);
        }

        mSosuuArr = SosuuList.ToArray();
    }
}


解説

3乗する素数を全探索してから、
二分法で、可能なもう片方の素数の区間を求めてます。