自幂数,也被称为阿姆斯特朗数,是一种特殊类型的数,在数学上具有一个有趣的性质:一个 n
位的正整数,其各个位上的数字的 n
次幂之和等于它本身。
这里是自幂数的定义步骤:
确定位数 (n
): 首先,要确定一个数是几位数。例如,153
是一个三位数,因此 n = 3
。
计算每个位上的数字的 n
次幂:接着,将该数的每个位上的数字取出来,分别计算其 n
次幂。对于 153
,计算如下:
1
?的三次幂是?1
5
?的三次幂是?125
3
?的三次幂是?27
计算这些幂的和:将上一步中得到的所有幂相加。对于 153
,其和是 1 + 125 + 27 = 153
。
验证和是否等于原数:如果这个总和等于原来的数,则称该数为自幂数。所以,153
是一个自幂数,因为 1^3 + 5^3 + 3^3 = 153
。
不同位数的自幂数有不同的名称:
153
,还包括?370
、371
?和?407
。1634
,因为?1^4 + 6^4 + 3^4 + 4^4 = 1634
。54748
,因为?5^5 + 4^5 + 7^5 + 4^5 + 8^5 = 54748
。自幂数不仅局限于三位数,但随着位数的增加,自幂数也变得越来越稀少。自幂数是数学中的一个奇特现象,通常用于编程练习和算术游戏中。在数学理论中,除了被当作一种趣题外,并没有特别的意义。
我们常说的水仙花数就是三位的自幂数。
打印0~100000内的自幂数:
#include <stdio.h>
#include <math.h>
int CountDigit(int x)//判断数字的位数
{
int counter = 0;
while (x)
{
x /= 10;
counter++;
}
return counter;
}
int main()
{
int i = 0,j = 0,s = 0,num = 0;
for (i = 0; i <= 100000; i++)
{
num = i;
int digits = CountDigit(i);
for(s = 0,j = 0;j < digits;j++)
{
s += (int)pow(num % 10, digits);
num /= 10;
}
if (s == i)
{
printf("%d ", i);
}
}
return 0;
}
运行结果:
代码分析:
CountDigit 函数:这个函数的目的是确定一个给定的整数 x
有多少位。它通过一个 while
循环实现:只要 x
不为0,就将 x
除以10,并将计数器 counter
加1。循环结束时,counter
就是 x
的位数。
main 函数:
i
,?j
,?s
,?num
。i
?将作为循环变量,j
?将在内部循环中使用,s
?用于累加幂的和,num
?存储?i
?的临时副本,防止?i
?的值在内部循环中被改变。for
?循环:for (i = 0; i <= 100000; i++)
,它将从0迭代到100000,检查每个数是否是自幂数。i
?的值赋给?num
,然后调用?CountDigit(i)
?函数得到当前?i
?的位数,这个值存储在?digits
?变量中,以便在后续计算中使用。for
?循环:for (s = 0, j = 0; j < digits; j++)
,用于计算?i
?的每一位上的数字的?digits
?次幂之和。每次循环:
num % 10
?提取?num
?的最后一位数字。pow(num % 10, digits)
?计算这个数字的?digits
?次幂。s += ...
?将这个幂加到?s
?上,s
?是一个累加器,用来计算所有幂的和。num /= 10
?通过整数除法去除?num
?的最后一位数字。s
(幂的和)等于原始的数?i
,则表明找到了一个自幂数,printf
?函数将其打印出来。整个程序的执行流程就是对从0到100000的每个整数检查是否为自幂数,并打印出这个范围内所有的自幂数。
编写一个程序用来打印菱形:
#include <stdio.h>
int main()
{
int i = 0, j = 0,n = 0;
scanf("%d", &n);//n应当为奇数
for (i = 0; i < (n / 2) + 1; i++)
{
for (j = 0; j < (n / 2) - i; j++)
{
printf(" ");
}
for (j = 0; j < 2 * (i + 1) - 1; j++)
{
printf("*");
}
printf("\n");
}
for (i = 0; i < n / 2; i++)
{
for (j = 0; j < i + 1; j++)
{
printf(" ");
}
for (j = 0; j < n - 2 * (i + 1); j++)
{
printf("*");
}
printf("\n");
}
return 0;
}
程序的工作流程如下所述:
用户输入:程序首先提示用户输入一个整数 n
,该值应该是奇数。
打印菱形的上半部:
for
?循环从?i = 0
?迭代到?i < (n / 2) + 1
。该循环负责打印菱形的上半部,包括最中间的一行。for
?循环打印前置空格。对于菱形的每一行,前置空格的数量是?(n / 2) - i
,这样星号后面的空格会随着每一行递增的?i
?而递减。for
?循环打印星号。每行的星号数量是?2 * (i + 1) - 1
,这保证了星号的数量随着每一行递增的?i
?而递增,每次增加两个星号(除了第一行)。printf("\n")
?打印一个换行符,以开始新的一行。打印菱形的下半部:
for
?循环从?i = 0
?迭代到?i < n / 2
。该循环负责打印除了最中间的行以外的菱形下半部分。for
?循环打印前置空格。对于下半部分的每一行,前置空格的数量是?i + 1
,这样随着下半部分每一行递增的?i
,前置空格也在递增。for
?循环打印星号。每行的星号数量是?n - 2 * (i + 1)
,这确保了星号的数量随着下半部分每一行递增的?i
?而递减,每次减少两个星号。printf("\n")
?打印一个换行符,以开始新的一行。最终,当所有循环执行完成时,如果 n
是一个奇数,你将得到一个完整的菱形图案。
这里是一个例子的输出,如果用户输入的 n
是 5
:
买汽水,一元一瓶,两个空瓶可以换一瓶汽水,20元可以喝几瓶。
#include <stdio.h>
int main()
{
int money = 0;
scanf("%d", &money);
int totalBottles = money;
int emptyBottles = totalBottles;
while (emptyBottles >= 2)
{
int newBottles = emptyBottles / 2;
totalBottles += newBottles;
emptyBottles = emptyBottles % 2 + newBottles;
}
printf("%d\n", totalBottles);
return 0;
}
程序分析:
运行结果:
#include <stdio.h>
int Func(int totalBottles, int emptyBottles)
{
if (emptyBottles < 2)
{
return totalBottles;
}
int newBottles = emptyBottles / 2;
return Func(totalBottles + newBottles, emptyBottles % 2 + newBottles);
}
int main()
{
int money = 0;
scanf("%d", &money);
printf("%d\n", Func(money, money));
return 0;
}
程序执行的流程大致如下:
程序启动后,进入main
函数,这是每个C程序的入口点。
程序声明了一个整型变量money
,用来存放用户通过标准输入提供的金额。
程序调用scanf
函数等待用户输入一个整数,该整数代表用户用来购买汽水的金额。输入的整数将被保存在money
变量中。
输入完毕后,程序调用Func
函数,将money
作为参数传入,这里有两个作用:一是表示初始时用这些钱可以直接买到的汽水数量,二是同样数量的空瓶可以开始进行换购。
Func
函数内部,首先检查当前的空瓶数量是否足够兑换更多的汽水。如果不足2个,则无法继续兑换,函数返回当前统计到的汽水总瓶数。
如果当前空瓶数量足够换更多汽水(即2个或2个以上),则计算能够兑换的新汽水瓶数,并更新空瓶数量(包括兑换后剩余的空瓶和新的空瓶)。
Func
利用递归调用自身,将更新后的汽水总数和空瓶数量作为新的参数,继续上述兑换过程。
当emptyBottles
不再足以兑换新的汽水时,递归结束,Func
函数返回最终计算的汽水总瓶数。
main
函数接收到Func
函数返回的总瓶数后,通过printf
函数输出到控制台。
最后,main
函数执行完毕,返回0,标志着程序的正常结束。
运行结果: