天天看點

PAT乙級1005 繼續(3n+1)猜想 (25分)(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

#include<stdio.h>
#include<stdlib.h>
int *array;
void jugment(int a,int n){
	int i;
	int flag=1;
	while(a!=1&&a!=0){
		if(a%2==0)
			a=a/2;
		else
			a=(3*a+1)/2;
		for(i=0;i<n;i++){
			if(a==array[i]){
				array[i]=0;
			}
		}
	}
}
void input(int n){	
	int i;
	array=(int*)calloc(n,sizeof(int));
	for(i=0;i<n;i++){
		scanf("%d",&array[i]);
	}
	for(i=0;i<n;i++)
	{
		jugment(array[i],n);
	}
}

void sort(int n){
	int i,j,t;
	for(i=0;i<n-1;i++){
        for(j=0;j<n-1-i;j++){
            if(array[j]<array[j+1]){
                t=array[j];
                array[j]=array[j+1];
                array[j+1]=t;
            }
        }
    }
}
void main(){
	int n;
	int i;
	scanf("%d",&n);
	input(n);
	sort(n);
	for(i=0;i<n;i++){
		if(array[i]!=0){
			if(array[i+1]==0||i==n-1)
				printf("%d",array[i]);
			else
				printf("%d ",array[i]);
		}
			
	}
}
           

解析:

該題的具體思路就是在驗證每個數的時候,将每次參與計算的數字與數組中的數進行比較,如有相同(覆寫數)則将該數在數組中做一個标記(我這裡均記為0),最後數組裡沒有标記的數(關鍵數)輸出即可

注:

1.這裡的數組我采用了動态輸入,也可以根據題目限制直接定義動态數組array[100]

2.因為不想把數組傳來傳去,所有直接偷懶定義為了全局變量>_<

3.這道題是自己添來添去,随便憑感覺做出來的,應該不是最優解(在jugment()函數裡每進行一次計算都要周遊一次數組進行判斷,時間複雜度并不理想,不知道有沒有更好的解決辦法,歡迎各位同僚提供方案,共同讨論)

繼續閱讀