PAT乙級1005 繼續(3n+1)猜想 (25)

PAT乙級1005  繼續(3n+1)猜想 (25)

時間限制
400 ms
內存限制
65536 kB
代碼長度限制
8000 B
判題程序
Standard
作者
CHEN, Yue

卡拉茲(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;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章