`
Touch_2011
  • 浏览: 290469 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

求21位水仙花数(C语言实现)

阅读更多
/*
 * 21位水仙花数
 */

#include<stdio.h>
#include<string.h>
#include<time.h>

#define DIGIT 21

char pow[DIGIT][50]={0};//存储0到9的DIGIT次方
int countNumber[10];//0-9的个数
char powDigit[10][DIGIT+1][DIGIT*3];//存储(0-9的21次方)*(0-9的个数)
char countDigit[][3]={"0","1","2","3","4","5","6","7","8","9","10","11","12",
"13","14","15","16","17","18","19","20","21"};

//大整数加法
void add(char* result,char* a,char* b)
{
	int temp[50]={0};
	int k=0,j,i;
	i=strlen(a)-1,j=strlen(b)-1;
	//相加
	while(i>=0 && j>=0){
		temp[k++]=(a[i--]-'0')+(b[j--]-'0');
	}
	while(i>=0)
		temp[k++]=a[i--]-'0';
	while(j>=0)
		temp[k++]=b[j--]-'0';
	//处理进位,使temp中各个元素的值在0--9之间
	for(i=0;i<k;i++){
		temp[i+1]+=temp[i]/10;
		temp[i]%=10;
	}
	while(temp[i]>9){
		temp[i+1]+=temp[i]/10;
		temp[i]%=10;
		i++;
	}
	//把结果存入result字符串中
    k=i;
	j=0;
	for(i=k;i>=0;i--){
		if(j==0 && temp[i]==0)
			continue;
		result[j++]=temp[i]+'0';
	}
	if(j==0)
    	result[j++]='0';
	result[j]=0;
}

//大整数减法(a>b)
void sub(char* result,char* a,char* b)
{
	int temp[50]={0};
	int k=0,j,i;
	i=strlen(a)-1,j=strlen(b)-1;
	//相减
	while(i>=0 && j>=0){
		temp[k++]=(a[i--]-'0')-(b[j--]-'0');
	}
	while(i>=0)
		temp[k++]=a[i--]-'0';
    
	//使temp中各个元素的值在0--9之间
	for(i=0;i<k-1;i++){
		if(temp[i]<0){
			temp[i]+=10;
			temp[i+1]-=1;
		}
	}
	//把结果存入result字符串中
    k=i;
	j=0;
	for(i=k;i>=0;i--){
		if(j==0 && temp[i]==0)
			continue;
		result[j++]=temp[i]+'0';
	}
	if(j==0)
    	result[j++]='0';
	result[j]=0;
}

//大整数乘法
void multiply(char* result,char* a,char* b)
{
	int temp[50]={0};
	int k=0,j,i;
	int len1=strlen(a),len2=strlen(b);
	//相乘
	for(i=len1-1;i>=0;i--){
		k=len1-1-i;
		for(j=len2-1;j>=0;j--){
    		temp[k++]+=(a[i]-'0')*(b[j]-'0');
		}
	}
	//处理进位,使temp中各个元素的值在0--9之间
	for(i=0;i<k;i++){
		temp[i+1]+=temp[i]/10;
		temp[i]%=10;
	}
	while(temp[i]>9){
		temp[i+1]+=temp[i]/10;
		temp[i]%=10;
		i++;
	}
	//把结果存入result字符串中
    k=i;
	j=0;
	for(i=k;i>=0;i--){
		if(j==0 && temp[i]==0)
			continue;
		result[j++]=temp[i]+'0';
	}
	if(j==0)
    	result[j++]='0';
	result[j]=0;
}

//给pow数组赋值,计算出0到9的DIGIT次方
void init()
{
	int i,j;
	strcpy(pow[0],"0");
	strcpy(pow[1],"1");
	for(i=2;i<=9;i++){
		pow[i][0]='1';
		for(j=1;j<=DIGIT;j++)
	    	multiply(pow[i],pow[i],countDigit[i]);
	}
	for(i=0;i<10;i++)
		for(j=0;j<=DIGIT;j++)
	    	multiply(powDigit[i][j],pow[i],countDigit[j]);
}

//判断是否是水仙花数
int judge()
{
	int i,temp;
	static char sum[50]={'0',0};//保存上一次的结果
	int tempCountNum[10]={0};
	static int laseNum[10]={0};//保存上一次的各个数字的个数
	for(i=1;i<10;i++){
		if((temp=countNumber[i]-laseNum[i])<0){
    		sub(sum,sum,powDigit[i][-temp]);
			laseNum[i]+=temp;
		}
		else if(temp>0){
			add(sum,sum,powDigit[i][temp]);
			laseNum[i]+=temp;
		}
	}
    
	for(i=0;i<DIGIT;i++)
    	switch(sum[i]){
    		case '0':tempCountNum[0]+=1;break;
     		case '1':tempCountNum[1]+=1;break;
    		case '2':tempCountNum[2]+=1;break;
    		case '3':tempCountNum[3]+=1;break;
    		case '4':tempCountNum[4]+=1;break;
    		case '5':tempCountNum[5]+=1;break;			
    		case '6':tempCountNum[6]+=1;break;
	    	case '7':tempCountNum[7]+=1;break;
     		case '8':tempCountNum[8]+=1;break;
    		case '9':tempCountNum[9]+=1;break;
	}
	for(i=0;i<10;i++)
		if(countNumber[i]!=tempCountNum[i])
			return 0;
	puts(sum);
	return 1;
}


//寻找DIGIT位水仙花数
void findNumber(int n,int count)
{
	int i,max=DIGIT;
    int start=0;
    if(n==0){
		countNumber[0]=DIGIT-count;
		judge();
		return;
	}
	switch(n){
	case 9:max=9;break;
	case 8:max=21;break;
	default:max=20;break;
	}
	for(i=max;i>=start;i--){
		countNumber[n]=i;
    	if(count+i>DIGIT)
	     	continue;
		if(countNumber[9]==0 && countNumber[8]<10)
			return;
    	findNumber(n-1,count+i);
	}
}

void main()
{
	int start=clock();
	init();
	printf("21位水仙花数有:\n");
	findNumber(9,0);
	printf("用时:%d ms\n",clock()-start);
}

 

0
0
分享到:
评论
6 楼 zh1159007904 2012-03-05  
大侠,你这个程序的递归部分看不懂,能不能麻烦解释一下递归的思路,谢谢!!
5 楼 shenma_IT 2011-12-31  
我是一楼的神马_CS哦 再次表示感谢!!
4 楼 shenma_IT 2011-12-31  
好 万分感谢 !!
3 楼 Touch_2011 2011-12-28  
shenma_CS 写道
你好! 我看了你的代码 有好多让我佩服的地方,真的,我是群上看到这连接,点击看到的 嗨!废话不多说,我想问下大侠你那大整数乘法那我看不懂 能不能说详细一点啊!

乘法是模拟数学上两个数相乘,但在处理进位方面可能有点不同。比如数a乘以数b,把a的个位数依次乘以b的每一位,a的个位乘完b的一位时并不急于进位,而是把每次相乘的结果保存加起来作为一个数组元素保存在数组中....最后再处理进位问题。

其他:这个程序主要在于代码优化,主要是要减少调用大整数加减乘函数的次数。第一次写出这个程序,运行时间是90秒左右、后来采用先存储(0-9的21次方)以空间换时间、优化到30秒左右,最后再judge函数中采用保存上一次结果的方法(有点动态规划的味道),时间优化到10秒左右。这些优化不是一次就想到的,是我跟另外一个同学一起想到的。所以其实我并不是什么大侠

还有就是:在java提供的大整数类中是采用int数组来处理大整数的,感觉效率会高一些。我还有个同学他是我们几个人中最早写出这个程序的,时间只有7秒,但是我们都看不懂他的代码。
如果你有更优化的算法,记得给我留言啊
2 楼 Touch_2011 2011-12-28  
乘法是模拟数学上两个数相乘,但在处理进位方面可能有点不同。比如数a乘以数b,把a的个位数依次乘以b的每一位,a的个位乘完b的一位时并不急于进位,而是把每次相乘的结果保存加起来作为一个数组元素保存在数组中....最后再处理进位问题。
1 楼 shenma_CS 2011-12-26  
你好! 我看了你的代码 有好多让我佩服的地方,真的,我是群上看到这连接,点击看到的 嗨!废话不多说,我想问下大侠你那大整数乘法那我看不懂 能不能说详细一点啊!

相关推荐

    水仙花数c语言程序.md

    水仙花数c语言程序(使用C语言实现筛选水仙花数).md水仙花数c语言程序(使用C语言实现筛选水仙花数).md水仙花数c语言程序(使用C语言实现筛选水仙花数).md水仙花数c语言程序(使用C语言实现筛选水仙花数).md水仙...

    水仙花数c语言程序水仙花数c语言程序

    水仙花数c语言程序 C语言中的水仙花数,是指一个 n 位数,它的每个位上的数字的n次方之和等于它本身。比如,153就是一个水仙花数,因为 1^3 + 5^3 + 3^3 = 153,这样的数字在数学上称为“自幂数”。 水仙花数是一类...

    C语言实现求水仙花数

    “水仙花说”是一个三位说,其各位数字立方和等于改数本身,本程序用c实现求水仙花数

    C语言编程求水仙花数

    在计算机编程领域,"水仙花数"是一个有趣的概念,主要与数字的算术特性相关。水仙花数,也称为 ...因此,"C语言编程求水仙花数"是一个很好的教学实例,能够激发初学者的兴趣并加深他们对数字特性和程序设计的理解。

    C语言求水仙花数

    ### C语言求水仙花数 #### 知识点概览 1. **水仙花数定义** 2. **C语言基础语法** - 变量声明与赋值 - 循环结构:`for`循环 - 条件判断:`if`语句 3. **算法实现** - 三位数分解 - 数字立方和计算 4. **代码...

    C语言 实现1000以内的水仙花数的程序

    程序中的数字范围可以自己改,很简单. 利用for()循环很简单就找到水仙花数。

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

    一个21位的整数,它的各个位数的21次方的和加起来等于它本身. 要求:程序在三分钟内完成,C语言实现. (有注释)

    C语言编程实现输出100—999之间的水仙花数

    在探讨如何用C语言编程实现输出100到999之间的水仙花数之前,我们首先需要理解几个核心概念:水仙花数、循环结构、条件判断以及数学运算。 ### 水仙花数的概念 水仙花数(Narcissistic number),又称为自恋数或...

    水仙花数c语言源码.zip

    水仙花数,又称自恋数或阿姆斯特朗数,是指一个三位数,其各位数字的立方和等于该数本身。例如,153是一个水仙花数,因为1^3 + 5^3 + 3^3 = 153。在C语言中,我们可以编写一个程序来寻找所有的水仙花数。以下是一个...

    水仙花数c语言程序zip

    在这样的文件中,你可能会找到源代码、编译脚本、测试用例和其他与水仙花数C语言程序相关的资源。 学习和理解这个程序有助于提升C语言的编程技能,包括理解数值计算、控制流程和基本的输入输出操作。同时,这也是对...

    while循环实现水仙花数

    水仙花数是指一个 3 位数,它的每个位上的数字的 3次幂之和等于它本身(例如:1^3 + 5^3+ 3^3 = 153)。 输入代码: #include #include&lt;math.h&gt; main() { int a,b,c,n; n = 100; while(n) { a = (n % 10)...

    水仙花数c语言程序.docx

    ### 水仙花数C语言程序解析 #### 一、水仙花数定义与特点 水仙花数,也称为阿姆斯特朗数或自恋数,是一种特殊的正整数,它的特点是该数的各位数字的n次幂之和等于该数本身,其中n是该数的位数。例如,153是一个...

    水仙花数c语言程序v1.0.pdf

    ### 水仙花数C语言程序解析与实现 #### 一、水仙花数定义与特点 水仙花数,又称作阿姆斯特朗数(Armstrong number)或自恋数,是一种特殊的自然数。这类数的一个显著特点是,一个n位数的所有位数字的n次幂之和恰好...

    水仙花数c语言程序 zip

    水仙花数,又称超完全数字平衡数,是指一...然而,这个压缩包的内容与当前讨论的水仙花数C语言程序没有直接关联。如果你对动态规划感兴趣,可以解压文件,学习其中的相关内容,这将有助于提升你的算法设计和分析能力。

    水仙花数C语言程序.md

    在计算机编程中,尤其在C语言中,实现查找水仙花数是一个基础但富有教育意义的练习。水仙花数具备的一个显著特征是,它是一个n位数,且它的各位数字的n次幂之和恰好等于它本身。 从给定文件的标题和描述中我们可以...

    c语言代码水仙花数

    ### C语言实现水仙花数 #### 概述 水仙花数(Narcissistic number)也称为自恋数、超完全数字不变数或阿姆斯特朗数,是指一个 n 位数(n≥3),它的每个位上的数字的 n 次幂之和等于它本身。例如,153 是一个 3 ...

Global site tag (gtag.js) - Google Analytics