PAT 1005 乙等(繼續(3n+1)猜想) c++
卡拉茲(Callatz)猜想已經在1001中給出了描述。在這個題目裡,情況稍微有些複雜。
當我們驗證卡拉茲猜想的時候,為了避免重複計算,可以記錄下遞推過程中遇到的每一個數。例如對n=3進行驗證的時候,我們需要計算3、5、8、4、2、1,則當我們對n=5、8、4、2進行驗證的時候,就可以直接判定卡拉茲猜想的真偽,而不需要重複計算,因為這4個數已經在驗證3的時候遇到過了,我們稱5、8、4、2是被3“覆蓋”的數。我們稱一個數列中的某個數n為“關鍵數”,如果n不能被數列中的其他數字所覆蓋。
現在給定一系列待驗證的數字,我們只需要驗證其中的幾個關鍵數,就可以不必再重複驗證餘下的數字。你的任務就是找出這些關鍵數字,並按從大到小的順序輸出它們。
輸入格式:每個測試輸入包含1個測試用例,第1行給出一個正整數K(<100),第2行給出K個互不相同的待驗證的正整數n(1<n<=100)的值,數字間用空格隔開。
輸出格式:每個測試用例的輸出佔一行,按從大到小的順序輸出關鍵數字。數字間用1個空格隔開,但一行中最後一個數字後沒有空格。
輸入樣例:6 3 5 6 7 8 11輸出樣例:
7 6
思路:此題在1001題的基礎上有了新的要求,為找到關鍵數需按輸入順序依次判斷每個數是否會覆蓋輸入數字(Hailstone(n) 序列的求解過程,不瞭解的可以去網上直接搜尋Hailstone序列),我的求解思路是用一個a[101]的陣列來記錄序列中出現的小於等於100的數的次數,如果是關鍵數,那麼只會在輸入的時候出現一次,a[n]==1成立。新學的vector的使用,牛刀小試。用一個vector<Int> 陣列來記錄輸入的待驗證數,使用sort
使用sort實現降序排序(預設升序):
bool compare(int i, int j){
return j<i;
}
sort(a.begin(),a.end(),compare);
#include <iostream> #include <vector> #include <algorithm> using namespace std; bool compare(int i, int j){ return j<i; } int main() { int n(0); //待驗證整數個數 cin >> n; vector<int> a(100); //記錄(3n+1)過程中出現每個數的次數 vector<int> b(n); //儲存每個待驗證整數 vector<int>::iterator it; for(it=b.begin();it!=b.end();it++){ int temp; cin >> *it; temp = *it; a[temp]++; if(temp==1){ a[temp]++; }else{ while(temp!=1){ if(temp%2==0){ temp/=2; if(temp<=100) //超過100無意義,不需記錄 a[temp]++; }else{ temp=(3*temp+1)/2; if(temp<=100) a[temp]++; } } } } sort(b.begin(),b.end(),compare); //按降序排序 int count(0); //記錄關鍵數個數 vector<int> key(1); // 儲存關鍵數 for(it=b.begin();it!=b.end();it++){ if(a[*it]==1){ key[count++]=*it; key.resize(count+1); } } //按要求輸出結果 for(it=key.begin();it!=key.end()-1;it++){ if(it!=key.end()-2){ cout << *it << " "; } else{ cout << *it; } } return 0; }