【PAT】B1027 打印沙漏

爲了這道題去複習了一下等差公式 大概長這樣(上一次複習這個還是大一考高數的時候)

 

思路:

步驟1

我們把沙漏看成兩個三角形,要求以下三個數據:

            1.底邊字符數 設爲x

            2.每行非空格字符輸出前要輸出多少個空格

            3. 需要剩下多少個題目給定的字符不輸出

步驟2: 計算x

先求出總項數,然後由等差數列求和公式可以得出單個三角形的總字符數爲1 + 3 + 5 + ... + x = ((1 + x) * (1 + x) / 2) / 2

這個計算過程可以看上面那張圖的例子

然後可以算出總字符數(即兩個三角形相加,減去重疊的“沙漏的中間點”) 爲((1 + x) * (1 + x) / 2)  - 1,由題意這個數應該小於等於n

那麼有式子((1 + x) * (1 + x) / 2)  - 1 <= n

解方程得 x = sqrt(2 * (n + 1)) - 1,易知因爲x是整數 這裏應該向下取整(有兩種方法 (int)強制類型轉換 或者用cmath頭文件裏的floor函數),我用了第二種方法, x = floor(sqrt(2 * (n + 1))) - 1,至此我們就把三角形的底邊算出來了。因爲這裏x只能是奇數,所以如果算出來的x是偶數的話還需要把它減一

步驟3:  計算某行應該輸出多少個空格

設某行輸出i個非空格字符 則需輸出(x - i)/ 2 個字符(很好推)

步驟4: 最後計算用不到輸出不了的字符數 = n - 總應輸出的非空格字符數 = n - ((1 + x) * (1 + x) / 2)  + 1

然後我們就可以寫代碼啦~

代碼:

#include <cstdio>
#include <cmath>
int main(){
	int n;
	char c;
	scanf("%d %c",&n,&c);
	int x = floor(sqrt(2.0 * (n + 1)))- 1;
	if (x % 2 == 0) x --;
	int used = (x + 1) * (x + 1)/2 - 1;//總共輸出的非空格字符數
	//輸出倒三角
	for (int i = x; i >= 1; i -= 2){//當前行的非空格字符數 
		for (int j = 0; j < (x - i)/2; j ++){//當前行的空格數 
			printf(" "); 
		} 
		for (int j = 0; j < i; j ++){
			printf("%c",c);
		}
		printf("\n");
	} 
	//輸出正三角 
	for (int i = 3; i <= x; i += 2){
		for (int j = 0; j < (x - i)/2; j ++){//當前行的空格數 
			printf(" "); 
		} 
		for (int j = 0; j < i; j ++){
			printf("%c",c);
		}
		printf("\n");		
	} 
	printf("%d\n",n - used);
	return 0;
}

 

 

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