1. 程式人生 > >中北大學NUC2017新生賽1008/NOJ-1988

中北大學NUC2017新生賽1008/NOJ-1988

題面:

家喻戶曉的中藥店

時間限制: 1000ms 記憶體限制: 65535KB

通過次數: 0 總提交次數: 0

問題描述

long_xiao和const_hhh是一對恩愛的夫妻。  

他們在京城經營著一家中藥店,夫妻二人醫術精湛、古道熱腸,雖然年過花甲,身體依然硬朗。更重要的是,他們的思維仍然十分活躍,不僅瞭解大家的要求,還能給他們許多驚喜。  

除了治病救人,他們的中藥配方還有舒筋活絡,排毒養顏的功效。正因為如此,中藥店門庭若市,甚至有人不遠千里,慕名而來。  

藥店裡藥材種類繁多,組成的配方也就非常多。為了提高服務質量,店裡的夥計灰來灰去將藥材和配方進行編號,灰來灰去可以通過配方的編號快速找到所需藥材的編號。

一天,店裡的夥計灰來灰去提議可以藉此機會來向大家普及一下數學知識,夫妻二人表示贊成,決定每週一在店門口的公告欄中釋出新的知識點。  

這週一他們提供了一個簡單但是有趣的知識點:  

“素數:一個大於1的自然數,除了1和它自身外,不能被其他自然數整除的數叫做素數“。  

到了週末,灰來灰去為了檢驗大家對知識點的掌握情況,使得今天的配方都由三種藥材組成,所需的三種藥材的編號都為素數,且加起來等於配方的編號。因為會有多種情況出現,灰來灰去使得三個素數的乘積最大。

現在,藥店會給你開出一劑配方,編號為n。如果你能把他拆成3個素數的和或者告訴灰來灰去無法拆成3個素數的和,那麼灰來灰去就可以快速找到藥材,並免費贈送你一副他們的鎮店配方。

輸入描述

輸入第一行包含一個正整數T,代表有T次配方的詢問。

對於每組資料,輸入包含一個正整數n(1<=n<=10000),代表配方的編號。

輸出描述

對於每組資料,如果n不能寫成三個素數的和,輸出-1。  
否則在一行從小到大輸出三個素數以及最大乘積。

樣例輸入
2  
20  
3
樣例輸出
2 7 11 154
-1

思路:先素數篩法打表,之後n^2遍歷素數表,第三個數為:配方的編號-遍歷得到的素數A-遍歷的素數B。如果第三個數也為素數,那麼判斷這三個數的乘積是否大於已得到的最大乘積,然後更新這個最大值。

坑點:三個數的乘積必須開long long,

#include<bits/stdc++.h>

typedef long long ll;

using namespace std;

bool a[10010];	 

int Prime[1500];  //素數表 
int cnt;

void p(){
	cnt = 0;
	memset(a,true,sizeof(a));
	a[0] = a[1] = false;	
	a[2] = true;
	for(int i = 2 ; i<=10000 ; i++){
		if(a[i]){
			Prime[cnt++] = i;
			for(int j = i+i ; j<=10000 ; j+=i){
				a[j] = false;
			}
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	p();
	
	int t ;
	cin>>t;
	while (t--){
		int n;
		cin>>n;
		ll maxn = -1;
		int x,y,z;
		for(int i = 0 ; i<cnt ; i++){
			for(int j = 0 ; j<cnt ; j++){
				int k = n-Prime[i]-Prime[j];   //k是得到的第三個數 
				if(k >=0 && a[k]){			//如果k是素數 
					if((ll)Prime[i]*Prime[j]*k > maxn){	
						maxn = (ll)Prime[i]*Prime[j]*k;
						x = min(Prime[i] , min(Prime[j] , k));
						z = max(Prime[i] , max(Prime[j] , k));
						y = Prime[i] + Prime[j] + k - x - z;
					}
				}
			}
		}
		if(maxn == -1){
			printf("-1\n");
		}
		else{
			printf("%d %d %d %lld\n",x,y,z,maxn);
		}
	}
	return 0;
}