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

Cマガ電脳クラブ(第047回) 素数列

問題

次のような数列を考える。
 P(n+1) = 2*P(n) - 1
つまり、「2倍して1を引く」ことで続く数列だ。

この漸化式を満たす「連続した8項」の数列があり、それがすべて素数であるという。
そんな数列はいくつもあるが、その中で最小の初項を持つものをみつけてほしい。


ソース

using System;
using System.Collections.Generic;

class Program
{
    const int Jyougen = 16000000; //数列の初項の上限
    static int[] SosuuArr;

    //エラトステネスの篩
    static void Eratosthenes()
    {
        var IsSosuuArr = new System.Collections.BitArray(Jyougen + 1);

        for (int I = 2; I <= IsSosuuArr.Count - 1; I++) {
            IsSosuuArr[I] = true;
        }
        for (int I = 2; I * I <= IsSosuuArr.Count - 1; I++) {
            if (IsSosuuArr[I] == false) continue;
            for (int J = I * 2; J <= IsSosuuArr.Count - 1; J += I) {
                IsSosuuArr[J] = false;
            }
        }
        var SosuuList = new List<int>();
        for (int I = 2; I <= IsSosuuArr.Count - 1; I++) {
            if (IsSosuuArr[I]) SosuuList.Add(I);
        }
        SosuuArr = SosuuList.ToArray();
    }

    static void Main()
    {
        var sw = System.Diagnostics.Stopwatch.StartNew();
        Console.WriteLine("数列の初項の上限を、{0}として検証します", Jyougen);
        Eratosthenes();

        //数列の次の項を求める
        Func<long, long> DeriveNextVal = pCurrVal => 2 * pCurrVal - 1;

        //素数でループ
        for (int P = 0; P <= SosuuArr.GetUpperBound(0); P++) {
            long CurrVal = SosuuArr[P];
            bool IsOK = true;
            var SuuretuList = new List<long>() { CurrVal };

            for (int N = 2; N <= 8; N++) {
                CurrVal = DeriveNextVal(CurrVal);
                SuuretuList.Add(CurrVal);
                if (IsSosuu(CurrVal) == false) {
                    IsOK = false;
                    break;
                }
            }
            if (IsOK) {
                Console.WriteLine("解は{0}で、数列は", SosuuArr[P]);
                SuuretuList.ForEach(X => Console.WriteLine("{0,10}", X));

                Console.WriteLine("経過時間={0}", sw.Elapsed);
                return;
            }
        }
    }

    //奇数が素数かを判定
    static bool IsSosuu(long pTargetOdd)
    {
        if (pTargetOdd <= Jyougen)
            return Array.BinarySearch(SosuuArr, (int)pTargetOdd) >= 0;

        for (long I = 3; I * I <= pTargetOdd; I += 2)
            if (pTargetOdd % I == 0) return false;
        return true;
    }
}


実行結果

数列の初項の上限を、16000000として検証します
解は15514861で、数列は
  15514861
  31029721
  62059441
 124118881
 248237761
 496475521
 992951041
1985902081
経過時間=00:00:15.0657181


解説

数列の初項の上限を決めて、求まった解を検証してます。