トップページに戻る    次のC#のサンプルへ    前のC#のサンプルへ

Problem87 素数の2乗と素数の3乗と素数の4乗の和で表される数

問題

素数の2乗と素数の3乗と素数の4乗の和で表される最小の数は28である.
50未満のこのような数は丁度4つある.

28 = 2の2乗 + 2の3乗 + 2の4乗
33 = 3の2乗 + 2の3乗 + 2の4乗
49 = 5の2乗 + 2の3乗 + 2の4乗
47 = 2の2乗 + 3の3乗 + 2の4乗
では, 5000万未満の数で, 素数の2乗と素数の3乗と素数の4乗の和で表される数は何個あるか?


ソース

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    //const int SikiiVal = 50;
    const int SikiiVal = 50000000;
    static int[] SosuuArr = new int[SikiiVal];

    //エラトステネスの篩
    static void Eratosthenes()
    {
        for (int I = 2; I <= SosuuArr.GetUpperBound(0); I++) {
            SosuuArr[I] = I;
        }
        for (int I = 2; I * I <= SosuuArr.GetUpperBound(0); I++) {
            if (I != 2 && I % 2 == 0) continue;

            if (SosuuArr[I] != 0) {
                for (int J = I * 2; J <= SosuuArr.GetUpperBound(0); J += I) {
                    SosuuArr[J] = 0;
                }
            }
        }

        SosuuArr = SosuuArr.Where(X => X != 0 && (long)X * X < SikiiVal).ToArray();
    }

    static void Main()
    {
        Eratosthenes();

        var List2Jyou = new List<int>();
        var List3Jyou = new List<int>();
        var List4Jyou = new List<int>();

        for (int I = 0; I <= SosuuArr.GetUpperBound(0); I++) {
            if ((long)SosuuArr[I] * SosuuArr[I] <= SikiiVal) {
                List2Jyou.Add(SosuuArr[I] * SosuuArr[I]);
            }
            else break;

            if ((long)SosuuArr[I] * SosuuArr[I] * SosuuArr[I] <= SikiiVal) {
                List3Jyou.Add(SosuuArr[I] * SosuuArr[I] * SosuuArr[I]);
            }
            if ((long)SosuuArr[I] * SosuuArr[I] * SosuuArr[I] * SosuuArr[I] <= SikiiVal) {
                List4Jyou.Add(SosuuArr[I] * SosuuArr[I] * SosuuArr[I] * SosuuArr[I]);
            }
        }

        int[] Arr2Jyou = List2Jyou.ToArray<int>();
        int[] Arr3Jyou = List3Jyou.ToArray<int>();
        int[] Arr4Jyou = List4Jyou.ToArray<int>();

        bool[] IsAppearArr = new bool[SikiiVal];

        for (int I = 0; I <= Arr4Jyou.GetUpperBound(0); I++) {
            long SumVal = Arr4Jyou[I];
            if (SikiiVal < SumVal) break;

            for (int J = 0; J <= Arr3Jyou.GetUpperBound(0); J++) {
                SumVal = (long)Arr4Jyou[I] + Arr3Jyou[J];
                if (SikiiVal < SumVal) break;

                for (int K = 0; K <= Arr2Jyou.GetUpperBound(0); K++) {
                    SumVal = (long)Arr4Jyou[I] + Arr3Jyou[J] + Arr2Jyou[K];
                    if (SikiiVal < SumVal) break;
                    IsAppearArr[SumVal] = true;
                }
            }
        }
        int AnsCnt = 0;
        for (int I = 0; I <= IsAppearArr.GetUpperBound(0); I++) {
            if (IsAppearArr[I]) {
                Console.WriteLine("{0}個目の解は{1}", ++AnsCnt, I);
            }
        }
    }
}


実行結果

省略
1097340個目の解は49999665
1097341個目の解は49999849
1097342個目の解は49999891
1097343個目の解は49999927


解説

Bool型の配列で存在有無を管理してます。