本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
思路
由题目“递减到1”得知,沙漏总行数一定是奇数。
先实现打印固定行数的上半部分沙漏,再复制修改成下半部分。
上半部分是首项为1,公差为2的等差数列,沙漏含符号数为2倍的等差数列求和再-1(中间部分的1个星星只有一层,2倍求和会多加1),这样就可以根据提供的星星符号数求得半个沙漏的最大行数。
上半部分数列递减,第i(i>=0)行要输出的星星数就是等差数列倒数第第n-i项的值 an=a1+(n-1)d,a1=1,d=2;输出的空格数递增。
下半部分相反
等 差 数 列 求 和 公 式 等差数列求和公式 等差数列求和公式 S = n a 1 + n ( n − 1 ) 2 d S=na_1+\frac{n(n-1)}{2}d S=na1+2n(n−1)d
代码
#include <stdio.h>
#include <math.h>
int main()
{
int sum,i,j; //sum=2n^2-1 n为沙漏一半的行数 n=√(sum+1)
char c;
scanf("%d %c",&sum,&c);
int n=sqrt((sum+1)/2),rest; //n为半个沙漏的最大行数
rest=sum-2*n*n+1; //rest为剩余符号数
for(i=0; i<n; i++){
for(j=i; j>0; j--)
printf(" ");
for(j=1+(n-i-1)*2; j>0; j--) //n-i是倒数第几行
printf("%c",c);
printf("\n");
}
for(i=1; i<n; i++){
for(j=n-i-1; j>0; j--)
printf(" ");
for(j=1+i*2; j>0; j--) //下半部分数列递增
printf("%c",c);
printf("\n");
}
printf("%d",rest);
return 0;
}
另一种判断方法
#include<stdio.h>
#include<math.h>
int main() {
int n,i,j,k;
char c;
scanf("%d %c",&n,&c);
int row=sqrt((n+1)/2.0),rest=n-2*row*row+1;
for (i=row; i>0; i--){
for (k=0; k<row-i; k++)
printf(" ");
for (j=0; j<i*2-1; j++)
printf("%c",c);
printf("\n");
}
for (i=2; i<=row; i++){ //跟上面反着 并少1个
for (k=row-i; k>0; k--) //完全跟上面反着
printf(" ");
for (j=0; j<i*2-1; j++)
printf("%c",c);
printf("\n");
}
printf("%d",rest);
return 0;
}