問題
- N (1000以下のN)までの素数を求めよ。
エラトステネスのふるいを、再帰プログラムにしよう。
実行例
どのようなふるい(フィルター)をしているのかを出力filtered p[4] filtered p[6] filtered p[8] filtered p[10] filtered p[12] filtered p[14] filtered p[16] filtered p[18] filtered p[20] filtered p[22] filtered p[24] filtered p[26] filtered p[28] filtered p[30] filtered p[9] filtered p[12] filtered p[15] filtered p[18] filtered p[21] filtered p[24] filtered p[27] filtered p[30] filtered p[25] filtered p[30] N : 30 2 3 5 7 11 13 17 19 23 29
解答例
[プログラム]
#include <stdio.h> #include <math.h> #define N 30 // プログラム中のNという文字を、30におきかえ void sieve (int i, int n, int p[]); void filter (int i, int m, int n, int p[]); int main (void) { int p[N+1]; int i; /* ① p[2] - p[N]を1に初期化 */ for(i = 2; i <= N; i++) p[i]=1; /* ② エラトステネスのふるい。 再帰版の呼び出し */ sieve (2, N, p); /* ③ 値が1のものは、素数 */ for(i = 2; i <= N1; i++) if(p[i]==1) printf("%3d", i); printf("\n"); return 0; } /* 再帰版 */ void sieve (int i, int n, int p[]) { if (i <= sqrt((float)n)) { /* 再帰条件 */ if (p[i] == 1) /* もし、素数なら */ filter (i, 2, n, p); /* 後ろをフィルター */ i++; sieve(i, n, p); /* 次のiから後ろをエラトステネス */ } /* 停止条件は、何もしないので、プログラムしない */ } void filter (int i, int m, int n, int p[]) { if (i*m <=n) { /* 素数iのm倍 */ if (p[i*m] ==1) { /* 1になっているかどうかをチェック。繰り返し代入になるが、しなくてもよい */ p[i*m] = 0; /* 素数ではない */ printf("filtered p[%d] \n", i*m); } m++; filter (i, m, n, p); /* 次のmについてfilter */ } /* 停止条件は何もしない */ }
コメント