中北大學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;
}