# Prime Number# Array# Greedy# Precomputation

c033 - 00406 - Prime Cuts

🔗 前往 ZeroJudge 原題

題目描述

題目要求找出 1 到 N 之間的所有質數,並根據給定的 C 值,輸出質數列表的中間部分。如果質數的數量 K 是偶數,則輸出 2C 個質數;如果 K 是奇數,則輸出 2C-1 個質數。如果 2C 或 2C-1 大於等於 K,則輸出所有質數。

解題思路

首先,使用埃拉托斯特尼篩法 (Sieve of Eratosthenes) 預先計算出 1 到 1000 之間的質數,並記錄每個數字是否為質數。然後,對於每組輸入 N 和 C,計算出 1 到 N 之間質數的數量 K。根據 K 的奇偶性以及 C 的值,計算出需要輸出的質數的起始位置和結束位置。最後,按照順序輸出指定範圍內的質數。

複雜度分析

  • 時間複雜度: O(N log log N + Q * K),其中 N 是篩選質數的上限 (1000),Q 是查詢次數,K 是 1 到 N 之間質數的數量。埃拉托斯特尼篩法的時間複雜度是 O(N log log N),對於每組查詢,需要遍歷最多 K 個質數,因此查詢部分的時間複雜度是 O(Q * K)。
  • 空間複雜度: O(N),主要用於儲存質數篩選的結果。

程式碼

#include <stdio.h>
int p[1001]={1},num[1001]={0};
int main(){
	int k=0;
	for(int i=2;i<=32;i++)
		for(int j=i*2;j<1001;j+=i)
			p[j]=1;
	for(int i=0;i<=1000;i++){
		if(p[i]==0)k++;
		num[i]=k;
	}
	int n,c;
	while(scanf("%d%d",&n,&c)>0){
		printf("%d %d: ",n,c); 
		if(num[n]%2){
			c=(c<<1)-1;
			if(c>=k){
				for(int i=1;i<=n;i++)
					if(p[i]==0)
						printf("%d ",i);
			}
			else{
				int t=0,max=(num[n]+c)/2,min=(num[n]-c)/2;
				for(int i=1;i<=n&&t<max;i++){
					if(p[i]==0){
						t++;
						if(t>min)
							printf("%d ",i);
					}
				}
			}
		}
		else{
			c<<=1;
			if(c>=k){
				for(int i=1;i<=n;i++)
					if(p[i]==0)
						printf("%d ",i);
			}
			else{
				int t=0,max=(num[n]+c)/2,min=(num[n]-c)/2;
				for(int i=1;i<=n&&t<max;i++){
					if(p[i]==0){
						t++;
						if(t>min)
							printf("%d ",i);
					}
				}
			}
		}
		printf("\n\n");
	}
}

Discussion