AOJ_2150 Matsuzaki Number
問題
M(N, P) = Nより大きい2つの素数の和をとることで得られる数を,小さいほうから順に並べたとき,P 番目の数
M(N, P)を求めよ。
0 ≤ N ≤ 100,000
1 ≤ P ≤ 100
解法
はじめにエラストテネスの篩で素数をたくさん求めておく。
Nより大きいP個の素数をみつける。
それらの素数の組み合わせで得られる和を優先度付きキューに入れてソート
P番目に取り出された値が答え。
実装
#include <cstdio> #include <queue> #include <algorithm> using namespace std; const int MAX_N = 201000; const int MAX_P = 100; bool prime[MAX_N]; int matsuzaki(int n, int P){ int pri[MAX_P]; //nより大きいP個の素数を貯めておく priority_queue<int, vector<int>, greater<int> > pque; //P個の素数を見つける int pri_n = 0; for(int i = n + 1; pri_n < P; i++){ if(prime[i]){ pri[pri_n] = i; pri_n++; } } //P個の素数を組み合わせてできるすべての数を優先度付きキューに for(int i = 0; i < P; i++){ for(int j = i; j < P; j++){ pque.push(pri[i] + pri[j]); } } //P番目に小さい数を取り出す int t; for(int i = 0; i < P; i++){ t = pque.top(); pque.pop(); } return t; } int main(){ int N, P; fill(prime, prime + MAX_N, true); prime[0] = prime[1] = false; for(int i = 2; i * i <= MAX_N; i++){ if(!prime[i]) continue; for(int j = i + i; j < MAX_N; j += i){ prime[j] = false; } } while(scanf("%d %d", &N, &P)){ if(N == -1) return 0; printf("%d\n", matsuzaki(N, P)); } return 0; }