1. 程式人生 > >NYOJ 28.大數階乘(大數問題)

NYOJ 28.大數階乘(大數問題)

/*描述
我們都知道如何計算一個數的階乘,可是,如果這個數很大呢,我們該如何去計算它並輸出它?
輸入
輸入一個整數m(0<m<=5000)
輸出
輸出m的階乘,並在輸出結束之後輸入一個換行符
樣例輸入
50
樣例輸出

30414093201713378043612608166064768844377641568960512000000000000

*/

對於大數問題,我們要有將大數與陣列結合的思想,可以利用類似於人工的方法求出有關大數的問題。

對於大數階乘來說,最重要的是如何將每個數的每位數與相對應的陣列元素儲存起來,就如算50的階乘,我們要先從1開始乘:

1*2=2,將2存到a[0]中,

2*3=6,將6儲存在a[0]中,

6*4=24,是兩位數,那麼24%10==4存到a[0]中,24/10==2存到a[1]中,

24*5=120,是三位數,那麼120%10==0存到a[0]中,120/10%10==2存到a[1]中,120/100==1存到a[2]中,

120*6=720,那麼720%10==0存到a[0]中,720/10%10==2存到a[1]中,720/100==7存到a[2]中,

...................

直到乘到50,將每一位數儲存為止。

#include <stdio.h>
int main()
{
	int carry,n,j;
	int a[40001];//儲存階乘的每一位數
	int digit;//表示階乘的位數
	int temp,i;   
	scanf("%d",&n);
	a[0]=1;
	digit=1;
	for(i=2; i<=n; i++)
	{
		for(carry=0,j=1; j<=digit; ++j)
		{
			temp=a[j-1]*i+carry;
			a[j-1]=temp%10;
			carry=temp/10;
		}
		while(carry)
		{
			a[++digit-1]=carry%10;
			carry/=10;
		}
	} 
	for(int k=digit; k>=1; --k)//倒序輸出每一位數
		printf("%d",a[k-1]);
	printf("\n");
    return 0;
}






/*
#include <stdio.h>
#include <string.h>
#define MAX 20000
int main()
{
	int arr[MAX]; 
	memset(arr,0,sizeof(arr));
	arr[0] = 1;
	int i,j,m,s;
	scanf("%d",&m);
	for(i=2;i<=m;i++)
	{
		int t = 0;
		for(j=0;j<MAX;j++)
		{
			s = arr[j] * i + t;//儲存計算的結果 
			arr[j] = s % 10;//把最低為存到陣列前面 
			t = s / 10;//計算進位 
		}
	}
	for(i=MAX-1;i>=0;i--)//把0都篩掉 
	{
		if(arr[i]) break;
	}
	for(j=i;j>=0;j--)//倒著輸出 
	{
		printf("%d",arr[j]);
	}
	printf("\n");
	return 0;
}
*/