1. 变种水仙花
题目描述:
变种水仙花数-Lily Number:把任意的数字,从中间拆分成两个数字,比如1461可以拆分成(1和461),(14和61),(146和1),如果所有拆分后的乘积之和等于自身,则是一个Lily Number。例如:
655=6 * 55 +65 * 5
1461 = 1 * 461 + 14 * 61 + 146 * 1
求出 5位数中的所有Lily Number。
输入描述:
无
输出描述:
一行,5位数中的所有LilyNumber,每两个数之间间隔一个空格
分析:
因为要输出5位数中所有的变种水仙花数,所以范围是10000到99999之间,然后判断是不是变种水仙花数。
假设:拆分12345这个数,会拆成1 2345、12 345、123 45、1234 5,如何得到题目中要求的方式呢,如:1234 5就是12345先%10,最后一位数字5先打印下来,然后再/10就会得到1234,以此类推就能得到相对应的数字,然后再根据题目给的示例在进行计算。
如下代码所示:
c
#include <stdio.h>
int main()
{
int i = 0;
for (i = 10000; i <= 99999; i++)
{
int j = 0;
int sum = 0;
for (j = 10; j <= 10000; j*=10)
{
sum += (i / j) * (i % j);
}
if (sum == i)
printf("%d ", i);
}
return 0;
}
//结果:14610 16420 23610 34420 65500
2. 使用循环的方法打印菱形
分析:
打印菱形的通用思路是拆成两部分:(以 * 为例)
- 上半部分:正三角形(从顶端到最宽的一行,逐行变宽)
- 下半部分:倒三角形(从次宽行到底端,逐行变窄)
上半部分(正三角)公式推导
步骤 1:列出行号与数量的对应表
我们先手动数出每一行的「空格组数」和「星号组数」(注意:代码里 printf(" ") 是 2 个空格为 1 组,printf("* ") 是星号 + 空格为 1 组,两者宽度一致,保证对齐)。
| 行号 i | 空格组数 | 星号组数 | 规律观察 |
|---|---|---|---|
| 0 | 6 | 1 | 空格最多,星号最少 |
| 1 | 5 | 3 | 空格 - 1,星号 + 2 |
| 2 | 4 | 5 | 空格 - 1,星号 + 2 |
| 3 | 3 | 7 | 空格 - 1,星号 + 2 |
| 4 | 2 | 9 | 空格 - 1,星号 + 2 |
| 5 | 1 | 11 | 空格 - 1,星号 + 2 |
| 6 | 0 | 13 | 空格为 0,星号最多(最宽行) |
步骤 2:推导空格数公式
观察空格组数:i=0 →1,i=1→2,i=5→6
规律:i 每增加 1,空格数减少 1,是递减的等差数列
首项(i=0)是 6,公差是 - 1
通项公式:空格数 = 6 - i
对应到循环条件:循环 j 从 0 开始,要执行 6-i 次,所以写 j < 6 - i
步骤 3:推导星号数公式
观察星号组数:i=0 → 1,i=1 → 3,i=2 → 5,i=6 →13
规律:i 每增加 1,星号数增加 2,是递增的等差数列
首项(i=0)是 1,公差是 2
通项公式:星号数 = 2*i + 1
对应到循环条件:循环 k 从 0 开始,要执行 2*i+1 次,所以写 k < 2 * i + 1。
下半部分(倒三角)公式推导
步骤 1:列出行号与数量的对应表
| 行号 i | 空格组数 | 星号组数 | 规律观察 |
|---|---|---|---|
| 0 | 1 | 11 | 对应上半部分 i=5 的行 |
| 1 | 2 | 9 | 空格 + 1,星号 - 2 |
| 2 | 3 | 7 | 空格 + 1,星号 - 2 |
| 3 | 4 | 5 | 空格 + 1,星号 - 2 |
| 4 | 5 | 3 | 空格 + 1,星号 - 2 |
| 5 | 6 | 1 | 对应上半部分 i=0 的行(顶端) |
步骤 2:推导空格数公式
观察空格组数:i=0 →1,i=1→2,i=5→6
规律:i 每增加 1,空格数增加 1,递增的等差数列
首项(i=0)是 1,公差是 1
通项公式:空格数 = i + 1
对应循环条件:j < i + 1。
步骤 3:推导星号数公式
观察星号组数:i=0 →11,i=1→9,i=5→1
规律:i 每增加 1,星号数减少 2,递减的等差数列
首项(i=0)是 11,公差是 - 2
通项公式:星号数 = 11 - 2*i
对应循环条件:k < 11 - 2 * i。
补充:11 这个数字怎么来的?
最宽行是 13 个星号,下半部分第一行比最宽行少 2 个,13-2=11,对应 i=0 的初始值。
c
int main()
{
char c = 0;
scanf("%c", &c);
int i = 0;//外层循环变量,用来控制总行数。
int j = 0;//内层第一个循环变量,用来控制每行开头的空格数量,实现菱形的缩进效果。
int k = 0;//内层第二个循环变量,用来控制每行打印的字符数量。
//打印上半部分7行
for (i = 0; i < 7; i++)
//i 从 0 到 6 循环,一共执行 7 次,对应菱形上半部分的 7 行。
{
// 循环1:打印每行开头的空格
for (j = 0; j < 6 - i; j++)
//i 越小,前面的空格越多;i 越大,空格越少。
{
printf(" ");//每次循环输出 2 个空格
}
// 循环2:打印每行的字符(带空格)
for (k = 0 ; k < 2 * i + 1;k++)
//i 每增加 1,字符数量增加 2 个。
{
printf("%c ",c);
}
printf("\n");
}
//打印下半部分6行
for (i = 0; i < 6; i++)
{
for (j = 0; j < i + 1; j++)
//i 越大,前面的空格越多,字符部分逐行缩进。
{
printf(" ");
}
for (k = 0; k < 11 - 2 * i; k++)
//每次输出字符 ,字符数量逐行递减 2 个。
{
printf("%c ",c);
}
printf("\n");
}
return 0;
}
输出结果示例(假设输入字符为 *):
*
* * *
* * * * *
* * * * * * *
* * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * *
* * * * * * *
* * * * *
* * *
*
说明:
- 程序首先读取一个字符(如
*) - 上半部分7行:每行开头空格递减,字符数量递增(1, 3, 5, ..., 13)
- 下半部分6行:每行开头空格递增,字符数量递减(11, 9, 7, ..., 1)
- 每打印一个字符后都带有一个空格,所以显示为字符间有间隔
- 每行开头的"空格组"实际上是两个空格,所以缩进效果明显```
总结
以后遇到任意大小的菱形 / 三角形,都按这个固定步骤来:
- 定行数:确定上半部分几行、下半部分几行,给行号 i 取值范围。
- 列表格:把 i 从 0 开始的每一行,手动数出空格数、字符数,填进表格。
- 找公差:看相邻两行的数量变化是加几还是减几,确定公差。
- 写公式:用「首项 + 公差 * i」写出通项公式。
- 验边界 :代入首行、末行、中间行,验证是否符合预期。
举个简单例子:5 行菱形(对角线 5 个字符)
上半部分 3 行,i=0、1、2
空格:2、1、0 → 公式 2 - i
字符:1、3、5 → 公式 2 * i + 1
下半部分 2 行,i=0、1
空格:1、2 → 公式 i + 1
字符:3、1 → 公式 3 - 2 * i