PAT乙級1005 繼續(3n+1)猜想 (25)
卡拉茲(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思路:設置數組num[]爲輸入的數,使用flag[]數組(初始化爲false)標記每一個num[i]所遍歷到的數,比如3遍歷到5、8、4、2,就把flag[5]、flag[8]、flag[4]、flag[2]標記爲true(注意此時flag[3]沒有被標記)。如此遍歷完num[]之後,再遍歷flag[num[i]],若爲真,說明num[i]可以被其它的數遍歷到;否則不可以,加入待輸出數組fnl[]。最後將fnl[]排序輸出即可。
#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
int i, n;
int index = 0;
scanf("%d", &n);
int *num = new int[n+1];
int *fnl = new int[n+1];
bool flag[101] = {false};
for(i = 0; i < n; ++i)
{
scanf("%d", &num[i]);
int tmp = num[i];
while(tmp != 1)
{
if( (tmp&1) == 0 )
{
tmp /= 2;
if(tmp <= 100) //防止越界
flag[tmp] = true;
}
else
{
tmp = (tmp*3+1)/2;
if(tmp <= 100) //防止越界
flag[tmp] = true;
}
}
}
for(i = 0; i < n; i++)
{
if(flag[num[i]] == false)
fnl[index++] = num[i];
}
sort(fnl, fnl+index);
printf("%d", fnl[--index]);
while(index--)
printf(" %d", fnl[index]);
return 0;
}