トップページに戻る
次のC#のサンプルへ
前のC#のサンプルへ
Problem249 素数の部分集合和
問題
S = {2, 3, 5, ..., 4999} を 5000 より小さい素数の集合とする.
要素の合計が素数となるような, S の部分集合の数を求めよ.
最下位の 16 桁を答えとして入力せよ.
ソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
const long Hou = 10000000000000000;
const int Jyougen = 4999;
static int[] mSosuuArr;
//エラトステネスの篩
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);
mSosuuArr = SosuuList.ToArray();
}
static void Main()
{
var sw = System.Diagnostics.Stopwatch.StartNew();
Eratosthenes();
int SumVal = mSosuuArr.Sum();
//場合の数[和]なDP表
long[] DPArr = new long[SumVal + 1];
DPArr[0] = 1;
int StaInd = 0;
for (int I = 0; I <= mSosuuArr.GetUpperBound(0); I++) {
for (int J = StaInd; 0 <= J; J--) {
if (DPArr[J] == 0) continue;
int NewJ = J + mSosuuArr[I];
DPArr[NewJ] += DPArr[J];
DPArr[NewJ] %= Hou;
}
StaInd += mSosuuArr[I];
}
long Answer = 0;
for (int I = 0; I <= DPArr.GetUpperBound(0); I++) {
if (DPArr[I] > 0 && IsPrime(I)) {
Answer += DPArr[I];
Answer %= Hou;
}
}
Console.WriteLine("Answer={0}。経過時間={1}", Answer, sw.Elapsed);
}
//試し割りで素数かを判定
static bool IsPrime(long pTarget)
{
if (pTarget == 2) return true;
if (pTarget % 2 == 0) return false;
for (long I = 3; I * I <= pTarget; I += 2) {
if (pTarget % I == 0) return false;
}
return true;
}
}
実行結果
Answer=9275262564250418。経過時間=00:00:15.5776796
解説
動的計画法で解いてます。