【洛谷】P1036 選數
阿新 • • 發佈:2018-12-01
洛谷P1036 選數
題目描述:
已知 n 個整數 x1,x2,…,xn,以及一個整數 k(k<n)。從 n 個整數中任選 k 個整數相加,可分別得到一系列的和。例如當 n=4,k=3,4 個整數分別為 3,7,12,19 時,可得全部的組合與它們的和為:
3+7+12=22
3+7+19=29
7+12+19=38
3+12+19=34。
現在,要求你計算出和為素數共有多少種。
例如上例,只有一種的和為素數:3+7+19=29。
輸入輸出格式:
輸入輸出格式
輸入格式:
鍵盤輸入,格式為:
n , k (1<=n<=20,k<n)
x1,x2,…,xn (1<=xi<=5000000)
輸出格式:
螢幕輸出,格式為:
一個整數(滿足條件的種數)。
我認為這是一道很適合做DFS入門題的水題
這道題說白了就是一道暴力
但如何暴力,怎樣的題該用暴力,這是不簡單的
這道題能很好得讓初學者認識到DFS並不僅僅侷限於棋盤(個人經驗)
演算法思路如下:
其實很簡單
暴力!暴力!暴力!
先確定第一個數,再向後列舉k-1個數
當累加到k個數時,判斷一下和是否為質數
接著,開始回溯
到前一個轉折點,再向後列舉“未走過的路”
當列舉到最後一個數時
轉折點提前,繼續列舉
若有更好見解,歡迎回復
以下程式碼僅供參考
#include<bits/stdc++.h>//萬能標頭檔案 using namespace std; int ans,n,k,a[50],i; bool check(int a)//判斷質數(a即為選擇的k個數之和) { int i; if(a<2) return false; for(i=2;i<=sqrt(a);i++) if(a%i==0) return false; return true; } void dfs(int num,int i,int sum)//(num表示已選數的個數,i表示下一個要列舉的數的位置,sum表示選數之和){ if(num==k)//當選了k個數時 { if(check(sum)) ++ans;//if所選數加起來是質數,ans累加 return; //回溯 } for(i;i<=n;i++)//只有這兩行才是核心程式碼(其實就是一個暴力,相當於n個數中列舉k個元素的集合) dfs(num+1,i+1,sum+a[i]);//以i向後列舉,由於前一步處理了邊界,這裡不需擔心會超過k個數 } int main() { cin>>n; cin>>k; for(i=1;i<=n;i++) cin>>a[i]; dfs(0,1,0);//(從0個數開始,下一步列舉第一個數,累加器暫時為0) cout<<ans;//完美輸出結果 return 0; }