题目传送门
https://pintia.cn/problem-sets/994805260223102976/problems/994805294251491328
这道题看起来不难,实际上也确实不难
我们观察可以发现要打印的沙漏可以看成两个同顶角的三角形组成。
如果看成数列的话,那么最顶上a1 = 1
之后就有递推式 an = 2*(1+2*(n-1)) 其中n是我们算的那一行
我们在求行数的时候只要用给定的符号数量每次减去那一行有的符号,如果减完之后符号数量小于零,那么就将操作回滚,退出循环;如果减完之后大于零就继续减
打印沙漏的时候后面的空格是不用打印的,不过打印的话也不难就是了,就是把打印前面的操作再来一遍
从顶行到三角形的顶角那一行,每一行的空格数都是加一的
代码如下
#include <stdio.h>
//有递推式, a1 = 1 an = 2 * (a1 + 2*(n-1))
int main(){
int n;
char b;
scanf("%d %c", &n, &b);
int row=1; //行数
n -= 1;
int count = 2;
while(1){
n -= (2*(1 + 2 * (count - 1))); //递推公式
if(n < 0){
n += (2*(1 + 2 * (count - 1)));
break;
}
row++; //行数加一
count++;
}
//打印沙漏
int c = count-1; //c是指定的输出字符最多的行数
int sumBlank = 0; //每行前面的空格数,逐行加一
for(;c > 1; c-=1){
for(int j=0; j < sumBlank; j++){
printf(" ");
}
sumBlank++;
for(int k=0; k<(1 + 2 * (c- 1)); k++){
printf("%c", b);
}
printf("\n");
}
for(int j=0; j<sumBlank; j++){
printf(" ");
}
printf("%c\n", b);
sumBlank--;
for(c = 2 ;c < count; c++){
for(int j=0; j<sumBlank; j++){
printf(" ");
}
sumBlank--;
for(int k=0; k<(1 + 2 * (c- 1)); k++){
printf("%c", b);
}
printf("\n");
}
printf("%d", n);
return 0;
}