快開學了纔開始學習之旅。
最近幾天在看數論基礎,然而看完1/4後卻發現後面的一竅不通。
萬分掙扎後,決定把它先放放,刷刷題。
學習還是不能浮躁,時刻讓自己平靜下來。
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
FROM:https://www.patest.cn/contests/pat-b-practise/1005
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int table[105][105];
int data[105];
void running(int i,int mom,int &k)
{
if(i!=mom)
table[mom][++k]=i;
if(i==1)return;
else if(i%2){
running((3*i+1)/2,mom,k);
return;
}
else
running(i/2,mom,k);
return;
}
bool exsearch(int father,int son)
{
if(!father||!son||father==son)return 0;
for(int i=1;i<table[father][0];++i){
if(son==table[father][i])
return 1;
}
return 0;
}
int main()
{
memset(table,0,sizeof(table));
memset(data,0,sizeof(data));
for(int i=2;i<101;++i)//draw up a table
running(i,i,table[i][0]);
int K;
scanf("%d",&K);
for(int i=0;i<K;++i)
scanf("%d",&data[i]);//loading
for(int i=0;i<K;++i){
for(int j=0;j<K;++j){
if(exsearch(data[i],data[j]))
data[j]=0;
}
}
sort(data,data+K);
printf("%d",data[K-1]);
for(int i=K-2;i>0&&data[i]!=0;--i){
printf(" %d",data[i]);
}
printf("\n");
return 0;
}
本來自己在紙上分析,構造出一顆樹,然而不會數據結構。
突發奇想打表比較,反正數也不大,超時?誰知道呢~!
試試就過了。dalao們的優化方法以後再看吧。