トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Problem187 半素数
問題
合成数とは2つ以上の素因数を含む整数のことである.
例えば15 = 3 × 5, 9 = 3 × 3, 12 = 2 × 2 × 3が合成数である.
30以下には丁度2つの素因数を含む合成数 (異なる素因数でなくてもよい) が, 10個存在する.
4, 6, 9, 10, 14, 15, 21, 22, 25, 26がそうである.
合成数 n < 10の8乗について,
丁度2つの素因数を含む合成数 (異なる素因数でなくてもよい) はいくつあるか.
ソース
using System;
using System.Collections.Generic;
class Program
{
const int Jyougen = 100000000;
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 (I != 2 && I % 2 == 0) continue;
if (IsSosuuArr[I]) {
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();
Eratosthenes();
int UB = SosuuArr.GetUpperBound(0);
int AnswerCnt = 0;
for (int I = 0; I <= UB; I++) {
//解が存在しない場合
if ((long)SosuuArr[I] * SosuuArr[I] >= Jyougen)
break;
int MaxInd = ExecNibunHou(I, UB);
int CurrCnt = MaxInd - I + 1;
AnswerCnt += CurrCnt;
}
Console.WriteLine("解は{0}。経過時間={1}", AnswerCnt, sw.Elapsed);
}
//2分法で、積が10の8乗未満の、最大の添字を返す
static int ExecNibunHou(int pL, int pR)
{
int L = pL;
int R = pR;
while (L + 1 < R) {
int Mid = (L + R) / 2;
//Console.WriteLine("L={0},R={1},Mid={2}。{3}*{4}={5}",
// L, R, Mid,
// SosuuArr[pL], SosuuArr[Mid], (long)SosuuArr[pL] * SosuuArr[Mid]);
bool IsOver = ((long)SosuuArr[pL] * SosuuArr[Mid] >= Jyougen);
if (IsOver) R = Mid;
else L = Mid;
}
return L;
}
}
実行結果
解は17427258。経過時間=00:00:05.6386783
解説
素数ごとに、掛けて10の8乗未満となる素数の個数を
2分法で求めてます。