[Project Euler] 来做欧拉项目练习题吧: 题目020
[Project Euler] 来做欧拉项目练习题吧: 题目020
周银辉
题目描述:
n! means n x (n  1) x ... x 3 x 2 x 1
 1) x ... x 3 x 2 x 1
For example, 10! = 10 x 9 x ... x 3 x 2 x 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.
Find the sum of the digits in the number 100!
题目分析:
求100!所得结果的各位数字之和
做法可以有两种:
一是做大数乗法,对于Java内置了BigInteger,或者Scheme可以实现无限精度的语言而已,问题就很简单。
否则自己模拟大数乗法,正如下面的multiply。
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
#define BF_SZ 1000 //buffer size
//将整数转换成字符串,并传出长度, 请手动释放返回值
//stdlib中的itoa也能完成类似的功能,
//但stdlib传入的buffer长度未知,一般会设置得比较大,而造成浪费
char* int_to_str(int n, int* length)
{	
	*length = floor(log10(abs(n!=0?n:1))) + 1;
	char *str = (char*)calloc(sizeof(char)*(*length+1));
	int i = *length-1;
	while(n!=0)
	{
		str[i] = n%10+48;
		n = n/10;
		i--;
	}
	return str;
}
//大数乗法,结果放在r中
void multiply(const char *a,const char *b, char *r)
{
	int i, j, *t, length_a, length_b, length_t; // t for temp
	length_a = strlen(a);
	length_b = strlen(b);
	length_t = length_a + length_b;
	t=(int*)malloc(sizeof(int)*length_t);
	for(i=0; i<length_t; i++)
	{
		t[i]=0;
	}
	for (i=0; i<length_a; i++)
	{
		for (j=0;j<length_b;j++)
		{
			t[i+j+1] += (a[i]-48)*(b[j]-48);
		}
	}
  	// 这里实现进位操作
	for (i=length_t-1; i>=0; i--)      
	{
		if(t[i]>=10)
		{
			t[i-1] += t[i]/10; 
			t[i]   %= 10;
		}
	}
	i=0;
	while(t[i]==0) 
	{
		i++;   // 跳过数前面的0
	}
	for (j=0; i<length_t; i++,j++)
	{
		r[j] = t[i]+48;
	}
	r[j]='\0';
	free(t);
}
int test(int n, char* buffer, char* temp)
{
	int i, j, k, a, b, c, p; //p for product
	int len;
	for(i=2; i<=n; i++)
	{
		char *str = int_to_str(i, &len);
		//printf("%s\t", str);
		//做buffer和str的大数乘法
		multiply(buffer, str, buffer);
		free(str);
	}
	return 0;
}
int main()
{
	char* buffer = (char*)malloc(BF_SZ*sizeof(char));
	char* temp   = (char*)malloc(BF_SZ* sizeof(char));
	memset(buffer, '0', BF_SZ);
	buffer[BF_SZ-1] = '1';
	memset(temp, '0', BF_SZ);
	test(100, buffer, temp);
	printf("buffer is %s\n", buffer);
	int i, len=strlen(buffer), count=0;
	for (i=0; i<len; i++) 
	{
		count += buffer[i]-48;
	}
	printf("the count is %d\n", count);
	free(buffer);
	free(temp);		
	return 0;
}
二是做大数阶乘:
#include <stdio.h>
#include <stdlib.h>
int buffer[1000];
void multiply(int buffer[],int n,int *length)
{
	int c=0, i, len=*length;
	for(i=0; i<len; i++)
	{
		buffer[i] = buffer[i]*n + c;
		c         = buffer[i]/10;
		buffer[i]%=10;
	}
	while(c!=0)
	{
		buffer[len++] = c%10;
		c /= 10;
	}
	*length=len;
}
main()
{
	buffer[0]=1;
	int i, n=100, len=1;
	for(i=2; i<=n; i++)
	{
		multiply(buffer, i, &len);
	}
	for(i=len-1; i>=0; i--)
	{
		printf("%d",buffer[i]);
	}
	printf("\n");
}
这种模拟大数运算的题目要求细心和耐性,其它便没什么了
推荐.NET配套的通用数据层ORM框架:CYQ.Data 通用数据层框架