用C语言实现21位水仙花数

水仙花数的概念

        “水仙花数(Narcissistic number)也被称为超完全数字不变数(pluperfect digital invariant, PPDI)、自恋数、自幂数、阿姆斯壮数或阿姆斯特朗数(Armstrong number),水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身。例如:1^3 + 5^3+ 3^3 = 153。”

        这次内容是用C语言实现21位水仙花数的输出。首先,二十一位数字在C语言中无法直接存储在一个变量中,因此我们需要借用到字符或者整形数组来存储与输出。

要实现这次目标,我们需要用到自定义函数,不然主函数中必将是混乱无比,不利于检查与纠错。为了减短其运行时间,首先我们需要考虑每次都要算二十一位数的二十一次方及其加和,必然是太过繁琐。所以,我们需要将0~9这十个数的二十一次方存起来。代码如下:

cun(int b[11][21])
 {
 	int i,j,k;

	for(i=0;i<10;i++)            //每个数的一次方存入
		b[i][20]=i;                
	for(k=2;k<10;k++)               //2~9后续次方的计算
	{
		for(i=1;i<21;i++)            //二十一次方的计算
		{
			for(j=20;j>=0;j--)        //为与数字对应的数组每一个元素乘以它本身
			{
				b[k][j]*=k;
			}
			for(j=20;j>0;j--)            //对进行一次次方后,将数组进行现实意义上的加和并存起来
			{
				b[k][j-1]+=b[k][j]/10;
				b[k][j]%=10;
			}
		}
	}
}

接下来就是判断二十一位数字并进行调用数组进行累积加和并存于一个新数组中,这里我们也需要考虑其加和是否大于我们优先确定的数值,比如存第一位数字的地方超出10或者等于0;在二十一位数字累计加和完成之后,我们需要考虑它是否与我们输入的二十一位数字的每个数字的个数是否相同,如果其相同则返回1,反之为0.为我们下一个函数段(输出)提供一个条件。代码如下:

int pows(int a[21],int b[11][21])
{
	int i,j,k,h,g,d,c,e,m[23]={0};
	for(i=0;i<21;i++)                //用来存放每一次二十一位数字二十一次方的加和
		b[10][i]=0;
		for(k=20;k>=0;k--)            //用来计算每一次二十一位数字二十一次方的加和
		{
			for(i=0;i<21;i++)
			{
				j=a[i];
				b[10][k]+=b[j][k];
			}
			m[k]=b[10][k];
		}
 		for(i=20,c=0,d=0;i>0;i--)      //用来对每一次二十一位数字二十一次方的加和进行错位加和
	 	{
			b[10][i]=(m[i]+c)%10;
			c=(m[i]+c)/10;
		}
		b[10][0]=(m[0]+c+d);
		
		for(i=0,e=1;i<10;i++)            //用俩判断两组数据的数字个数是否相同
		{
			for(k=0,g=0,h=0;k<21;k++)
			{
				if(a[k]==i)
					g++;
				if(b[10][k]==i)
					h++;
			}
			if(g!=h)
			{
				e=0;
				break;
			}
		}
	return e;
}

接下来就是输出函数了,这一块是没有任何问题的。代码如下:

Output(int e,int b[11][21])
{
	int i;
	if(e==1&&b[10][0]>0)
	{
		for(i=0;i<21;i++)
		{
			printf("%d",b[10][i]);
		}
		printf("\n");
	}
}

对数据的判断和输出弄完了,那么现在就是数据的输入了。首先我们要考虑用哪种方法进行输入,一个数一个数的输入肯定是太过于浪费时间了,所以我们可以用数字的个数进行输入,而每个位置上都是0~9必然会出现很多次的重复运算。那么我们为了避免重复以及缩短时间,则采用下一位数字不大于前一位数字,这样便将所有的可能输入进去。而我们要的是二十一位数字,那么第一个数第一次必然不能是0.然而我们自己可以运用上面的东西显示出0~9的21次方,可以算出21个7的21次方和是小于21一位数的,那么第一位数字我们是可以用数字8来开头的,再利用上面的数据,我们可以的得出10个9的21次方和是大于21位数的,那么我们第十个数的输入必然是不能大于8的。好了这一段的代码如下:

bian()
 {
 	int i,j,k,g,f=1,e=1,a[21],b[11][21]={0};
 	cun(b);
 	for(a[0]=8;a[0]<10;a[0]++)
	 for(a[1]=0;a[1]<=a[0];a[1]++)
	  for(a[2]=0;a[2]<=a[1];a[2]++)
       for(a[3]=0;a[3]<=a[2];a[3]++)
		for(a[4]=0;a[4]<=a[3];a[4]++)
		 for(a[5]=0;a[5]<=a[4];a[5]++)
		  for(a[6]=0;a[6]<=a[5];a[6]++)
		   for(a[7]=0;a[7]<=a[6];a[7]++)
			for(a[8]=0;a[8]<=a[7];a[8]++)
			 for(a[9]=0;a[9]<=a[8];a[9]++)
			  for(a[10]=0;a[10]<=a[9];a[10]++)
			   for(a[11]=0;a[11]<=a[10];a[11]++)
				for(a[12]=0;a[12]<=a[11];a[12]++)
				 for(a[13]=0;a[13]<=a[12];a[13]++)
				  for(a[14]=0;a[14]<=a[13];a[14]++)
				   for(a[15]=0;a[15]<=a[14];a[15]++)
					for(a[16]=0;a[16]<=a[15];a[16]++)
					 for(a[17]=0;a[17]<=a[16];a[17]++)
					  for(a[18]=0;a[18]<=a[17];a[18]++)
					   for(a[19]=0;a[19]<=a[18];a[19]++)
						for(a[20]=0;a[20]<=a[19];a[20]++)
						{
							if(a[0]<=8&&a[10]>=8&&a[9]!=9)     //利用数据的前期计算进行跳过
							{
								e=pows(a,b);
								Output(e,b);
							}
							else
								if(a[9]!=9)                 //利用数据的前期计算进行跳过
							{
								e=pows(a,b);
								Output(e,b);
							}
							
						}
}

好了本次的目的也就源码完成了,总代码如下:

#include<stdio.h>
cun(int b[11][21])
 {
 	int i,j,k,h;

	for(i=0;i<10;i++)
		b[i][20]=i;
	for(k=2;k<10;k++)
	{
		for(i=1;i<21;i++)
		{
			for(j=20;j>=0;j--)
			{
				b[k][j]*=k;
			}
			for(j=20;j>0;j--)
			{
				b[k][j-1]+=b[k][j]/10;
				b[k][j]%=10;
			}
		}
	}
}
int pows(int a[21],int b[11][21])
{
	int i,j,k,h,g,d,c,e,m[23]={0};
	for(i=0;i<21;i++)
		b[10][i]=0;
		for(k=20;k>=0;k--)
		{
			for(i=0;i<21;i++)
			{
				j=a[i];
				b[10][k]+=b[j][k];
			}
			m[k]=b[10][k];
		}
 		for(i=20,c=0,d=0;i>0;i--)
	 	{
			b[10][i]=(m[i]+c)%10;
			c=(m[i]+c)/10;
		}
		b[10][0]=(m[0]+c+d);
		
		for(i=0,e=1;i<10;i++)
		{
			for(k=0,g=0,h=0;k<21;k++)
			{
				if(a[k]==i)
					g++;
				if(b[10][k]==i)
					h++;
			}
			if(g!=h)
			{
				e=0;
				break;
			}
		}
	return e;
}
Output(int e,int b[11][21])
{
	int i;
	if(e==1&&b[10][0]>0)
	{
		for(i=0;i<21;i++)
		{
			printf("%d",b[10][i]);
		}
		printf("\n");
	}
}
 bian()
 {
 	int i,j,k,g,f=1,e=1,a[21],b[11][21]={0};
 	cun(b);
 	for(a[0]=8;a[0]<10;a[0]++)
	 for(a[1]=0;a[1]<=a[0];a[1]++)
	  for(a[2]=0;a[2]<=a[1];a[2]++)
       for(a[3]=0;a[3]<=a[2];a[3]++)
		for(a[4]=0;a[4]<=a[3];a[4]++)
		 for(a[5]=0;a[5]<=a[4];a[5]++)
		  for(a[6]=0;a[6]<=a[5];a[6]++)
		   for(a[7]=0;a[7]<=a[6];a[7]++)
			for(a[8]=0;a[8]<=a[7];a[8]++)
			 for(a[9]=0;a[9]<=a[8];a[9]++)
			  for(a[10]=0;a[10]<=a[9];a[10]++)
			   for(a[11]=0;a[11]<=a[10];a[11]++)
				for(a[12]=0;a[12]<=a[11];a[12]++)
				 for(a[13]=0;a[13]<=a[12];a[13]++)
				  for(a[14]=0;a[14]<=a[13];a[14]++)
				   for(a[15]=0;a[15]<=a[14];a[15]++)
					for(a[16]=0;a[16]<=a[15];a[16]++)
					 for(a[17]=0;a[17]<=a[16];a[17]++)
					  for(a[18]=0;a[18]<=a[17];a[18]++)
					   for(a[19]=0;a[19]<=a[18];a[19]++)
						for(a[20]=0;a[20]<=a[19];a[20]++)
						{
							if(a[0]<=8&&a[10]>=8&&a[9]!=9)
							{
								e=pows(a,b);
								Output(e,b);
							}
							else
								if(a[9]!=9)
							{
								e=pows(a,b);
								Output(e,b);
							}
							
						}
}
main()
{
	bian();
}

代码运行结果如下: 

 

 

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值