爲了這道題去複習了一下等差公式 大概長這樣(上一次複習這個還是大一考高數的時候)
思路:
步驟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;
}