51Nod-1057-N的階乘
阿新 • • 發佈:2019-02-13
輸入N求N的階乘的準確值。
Input
輸入N(1 <= N <= 10000)
Output
輸出N的階乘
Input示例
5
Output示例
120
遇見這道題,也是我的運氣,因為以前根本沒有想過這種高精度的題還可以這樣子做,太神奇了,先發一下我原來的做法。
#include <stdio.h>
#include <string.h>
#define _MAX 6
#define MAX_ 10000000
int product[MAX_];
int pro[MAX_], num[_MAX];
int rank = 1;
//遞迴進位函式
void Carrying(int tag,int i,int j,int *p)
{
p[i+j]+=tag;
if (i + j + 1 > rank || (i + j + 1 == rank && p[i + j] > 9))
{
rank++;
}
if (p[i+j]>9)
{
tag=p[i+j]/10;
p[i+j] %=10;
Carrying(tag, i+1, j, p); //寫成Carrying(tag, i, j+1, p);也成立,為了讓i+j遞增而已
}
return ;
}
//乘法
void multiplication(int N)
{
int i=0,j=0,numLen,productLen,tag;
for (i = 0; N > 0; i++)
{
num[i] = N % 10;
N /= 10;
}
numLen = i;
productLen = rank;
for (i = 0; i < productLen; i++)
{
pro[i] = product[i];
}
memset (product, 0, sizeof(int) * MAX_);
//逐位相乘
for (i=0; i<productLen; i++)
{
for (j=0; j<numLen; j++)
{
tag= pro[i] * num[j];
Carrying(tag, i, j, product); //遞迴
}
}
return ;
}
int main()
{
int N, i = 2, j;
scanf("%d", &N);
memset(product, 0, sizeof(int) * MAX_); //初始化product資料為0
product[0] = 1;
for (; i <= N; i++)
{
multiplication(i);
}
//倒序輸出結果
for (j = rank - 1; j >= 0; j--)
{
printf("%d",product[j]);
}
printf("\n");
}
這種做法比較細碎,所以在這道題的測試資料下,只過了五分之二的測試資料,剩下的悉數超時,所以,我不得不尋求其他更簡單的方法,於是乎,就遇見了下面這個巧妙的方法。
#include <stdio.h>
#define _MAX 100000000
int main()
{
int n, i, j, m;
long long a[10000], c;
scanf("%d",&n);
m = 0;
a[0] = 1;
for(i = 1; i <= n; i++)
{
c = 0;
for(j = 0; j <= m; j++)
{
a[j] = a[j] * i + c;
c = a[j] / _MAX;
a[j] %= _MAX;
}
if(c > 0)
{
m++;
a[m] = c;
}
}
printf("%lld", a[m]);
for(i = m - 1; i >= 0; i--)
printf("%0.8lld", a[i]);
printf("\n");
return 0;
}
這裡我們知道,如果簡單的用乘法去階乘,那麼不用多大,立馬就爆了資料範圍,於是,這道題的這個解法巧妙的對這個超級大的數進行了切分,具體切成多寬的看個人愛好,只要能夠用幾個資料型別裝下來就好,這裡我們劃分成了8個的寬度,每八位存一下,最後再進行格式化輸出,巧妙的避開了爆資料範圍的問題。看著程式碼理解起來並不難,提示一下,c和進位相關,m和切的段數相關,就這樣,相信大家看看都是可以理解的,如果無法理解,那麼只能說,回去學學數學吧,乖Y(^_^)Y!!!