1005 繼續 3n 1 猜想

2021-10-02 09:39:33 字數 4320 閱讀 1608

卡拉茲(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每個測試用例的輸出佔一行,按從大到小的順序輸出關鍵數字。數字間用 1 個空格隔開,但一行中最後乙個數字後沒有空格。

6

3 5 6 7 8 11

7 6
建立四個陣列。將所有計算的覆蓋數存起來,再和輸入資料對照。如果輸入資料有,則說明輸入的資料不是關鍵數,篩選之後,最後剩下的輸入資料就是關鍵數了。這種方法容易理解,但是技巧性顯然不足,因為需要將後面的所有數字的關鍵數都計算出來。實際上,後面的數字經過判斷,有些數字是不需要計算的。n=6

}使用vector容器儲存,使用的sort()函式進行排序。一次將所有資料存入vector,計算每個數字的覆蓋數之後,就將後面vector中屬於覆蓋數的數字進行標記,賦值為0。這樣後面只要進行非零數就可以跳過是覆蓋數的vector。最後進行sort()排序

vector知識點:

c++ vector 容器**基本用法:

#include < vector>

using namespace std;

//向量(vector)是乙個封裝了動態大小陣列的順序容器

//能夠存放任意型別

簡單介紹:vector《型別》識別符號(最大容量);

sort()函式:
sort()函式c++#include< algorithm>  //所屬標頭檔案

?sort(begin,end,cmp); //其中cmp引數可以省略,省略後預設公升序排序

?如果要進行降序排序,需要另外定義cmp函式:

;//將非keynum置零

for(

int j=

0;j}}

}sort

(m.begin()

,m.end()

,cmp)

;//根據cmp的返回值型別確定排序方式 // 2

for(

int i=

0;i) flag=1;

}return0;

}vector也可以不申請大小,動態申請,採用v.push_back(i)。但是一定不能先申請大小,又v.push_back(),因為這樣會把申請大小的vector都認為是0,也帶進去

#include

#include

#include

using

namespace std;

bool

cmp(

int a,

int b)

intmain()

; vector<

int> v;

for(

int i=

0;isort

(v.begin()

,v.end()

,cmp)

;for

(int i=

0;isize()

;i++)}

return0;

}

上面的公升級版可以很好地解決這個問題。但是隨之而來的問題是必須要使用者全部輸入才可以進行判斷。也就是現在根據使用者輸入的某乙個數字,只能針對之前輸入的資料有效。此次輸入的數字是不是關鍵數已經形成結論,無法在後續輸入計算後調整之前的是不是關鍵數的判斷。

帶來的問題也顯然,就是時間複雜度2*o(n)。因為前後有兩個0~n-1的for迴圈。

雜湊雜湊就可以解決這個問題,並且將時間複雜度降低到公升級版的一般,也就是o(n)。這也是理論上最低的時間複雜度了。

雜湊雜湊的思想是這樣的:類似於函式因變數與自變數的關係,自變數到因變數的對映只能是一對一和多對一。因此,在計算出使用者輸出的某個數字的覆蓋數之後,將覆蓋數部分放置在乙個新陣列中,並全部置1,這樣當有新的數字計算後使得原來不是覆蓋數的原始數字也會置1。這樣,最後剩下的就是沒有置1的數字,它們就是關鍵數。

這裡存在兩個對映:

每乙個inputnum,會將其覆蓋數全部置1;

每乙個輸入數字的序號對應乙個inputnum.

因此只要每乙個輸入數字序號對應的數字的雜湊陣列值仍然為0,就說明不是覆蓋數,就可以輸出。對應**3部分。

對每乙個輸入的數字n進行驗證,把驗證過的數字對應的arr標記為1,然後對這些輸入的數字從大到小排序,輸出所有arr=0的數字即為關鍵數字~

#include

#include

#include

using

namespace std;

int arr[

10000];

//定義了乙個全域性陣列 +

bool

cmp(

int a,

int b)

//int

main()

tmp/=2

;if(arr[tmp]==1

)break

; arr[tmp]=1

;}}sort

(m.begin()

,m.end()

,cmp)

;//根據cmp的返回值型別確定排序方式

for(

int i=

0;isize()

;i++)}

return0;

}

1005繼續3n 1猜想

卡拉茲 callatz 猜想已經在1001中給出了描述。在這個題目裡,情況稍微有些複雜。當我們驗證卡拉茲猜想的時候,為了避免重複計算,可以記錄下遞推過程中遇到的每乙個數。例如對n 3進行驗證的時候,我們需要計算3 5 8 4 2 1,則當我們對n 5 8 4 2進行驗證的時候,就可以直接判定卡拉茲猜...

1005 繼續 3n 1 猜想

卡拉茲 callatz 猜想已經在1001中給出了描述。在這個題目裡,情況稍微有些複雜。當我們驗證卡拉茲猜想的時候,為了避免重複計算,可以記錄下遞推過程中遇到的每乙個數。例如對n 3進行驗證的時候,我們需要計算3 5 8 4 2 1,則當我們對n 5 8 4 2進行驗證的時候,就可以直接判定卡拉茲猜...

1005 繼續 3n 1 猜想

時間限制 400 ms 記憶體限制 65536 kb 長度限制 8000 b 判題程式 standard 作者 chen,yue 卡拉茲 callatz 猜想已經在1001中給出了描述。在這個題目裡,情況稍微有些複雜。當我們驗證卡拉茲猜想的時候,為了避免重複計算,可以記錄下遞推過程中遇到的每乙個數。...