/* SuperCon 2004 予選問題 解答プログラム例 */ #include /* 問題文中で指定されたパラメータ */ #define N (12) /* SuperCon 数の素因数の個数 */ #define K (2004) /* 何番目の SuperCon 数を計算するか */ /* 定数 */ #define MAX_PRIME (65536) /* 素数表の最大値 */ #define MAX_CAND (16384) /* ヒープ cand の最大要素数 */ #define TRUE (1) /* 真 */ #define FALSE (0) /* 偽 */ /* 構造体 */ typedef struct { int number; /* SuperCon 数 */ int factor[N]; /* 素因数 */ } scnum_t; /* 変数 */ int next_prime[MAX_PRIME]; /* p の次の素数 */ scnum_t cand[MAX_CAND]; /* 次にくる SuperCon 数の候補 */ int n_cand = 0; /* ヒープ cand の要素数 */ /* 素数表の作成 (エラトステネスのふるい) */ void make_next_prime(void) { int mark[MAX_PRIME]; int prev_prime; int i, j; for(i = 2; i < MAX_PRIME; i++) { mark[i] = FALSE; } prev_prime = 0; for(i = 2; i < MAX_PRIME; i++) { if(!mark[i]) { next_prime[prev_prime] = i; prev_prime = i; for(j = i + i; j < MAX_PRIME; j += i) { mark[j] = TRUE; } } } } /* 指定された SuperCon 数を候補に追加 */ void add_to_cand(scnum_t s) { int i, p; scnum_t tmp; cand[n_cand] = s; ++n_cand; /* ヒープ条件の回復 */ i = n_cand - 1; while(i > 0) { p = (i - 1) / 2; if(cand[p].number < cand[i].number) break; tmp = cand[p]; cand[p] = cand[i]; cand[i] = tmp; i = p; } } /* 候補の中から最小の SuperCon 数を取り出す */ scnum_t get_next_cand(void) { int i, l, r; scnum_t s, tmp; s = cand[0]; cand[0] = cand[n_cand - 1]; --n_cand; /* ヒープ条件の回復 */ i = 0; while(i * 2 + 1 < n_cand) { l = i * 2 + 1; r = i * 2 + 2; if(r < n_cand && cand[r].number < cand[l].number) l = r; if(cand[i].number < cand[l].number) break; tmp = cand[i]; cand[i] = cand[l]; cand[l] = tmp; i = l; } return s; } /* SuperCon 数を 2^12 から順番に生成 */ int compute(int n) { scnum_t s, t; int p_old, p_new; int i, k; /* 最初の候補 2^12 を追加 */ s.number = 1 << N; for(i = 0; i < N; i++) s.factor[i] = 2; add_to_cand(s); k = 0; while(TRUE) { /* 次の SuperCon 数を取り出す */ s = get_next_cand(); /* n から数えて 2004 番目まで取り出したら終了 */ if(s.number >= n) { ++k; if(k == K) return s.number; } /* 次の候補を作る準備 */ i = 0; while(i < N && s.factor[i] == 2) { ++i; } /* 2 があればそれを 3 に置換した候補を追加 */ if(i > 0) { p_old = 2; p_new = next_prime[2]; t = s; t.number = t.number / p_old * p_new; t.factor[i - 1] = p_new; add_to_cand(t); } /* 2 以上の素因数のうち最小のものが単独で存在するときは,それを 次の素数で置換 */ if(i < N) { p_old = s.factor[i]; if(i == N - 1 || s.factor[i + 1] != p_old) { p_new = next_prime[p_old]; t = s; t.number = t.number / p_old * p_new; t.factor[i] = p_new; add_to_cand(t); } } } } /* メインルーチン */ int main(void) { int n; make_next_prime(); scanf("%d", &n); printf("%d\n", compute(n)); return 0; }