高精度阶乘
1w! 耗时0.3s
3w! 耗时3.0s
10w! 耗时50s
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
typedef long long ll;
ll MOD = 1e9; //进位的上限
ll cnt = 0; //记录数字位数
clock_t start; //记录开始时间
clock_t finish; //记录结束时间
typedef struct LNode {
ll data; //数据域
struct LNode* next; //后继结点指针域
}LNode, *LinkList;
//链表初始化
void InitList(LinkList& Head) { //建立链表
Head = new LNode; //分配空间
Head->next = NULL; //后继为空
}
//初始化
void Pretreatment(LinkList& Head) { //初始化,使得初始值为1
LinkList node = new LNode; //新结点分配空间
node->data = 1;
node->next = NULL;
Head->next = node;
}
//头插法
void Head_Insert(LinkList& Head, ll data) {
LinkList node = new LNode; //新结点分配空间
node->data = data; //赋值
node->next = Head->next; //新结点的后继指向头结点的后继
Head->next = node; //头结点的后继指向新结点
}
//计算一个数的位数
int Dight(ll num) {
int ans = 1;
for (int i = 10; i <= MOD; i *= 10) {
if (num / i < 1)
return ans;
else if (i == MOD)
return ans + 1;
else
ans++;
}
return 0;
}
//遍历Head链表,头插入ans指向的链表,插入后删除head所指向链表的每个结点
void turn(LinkList Head, LinkList& ans) {
LinkList p = Head->next, q;
while (p) {
q = p; //记录删除结点
Head_Insert(ans, p->data);
if (p->next == NULL) //Head链表已经到达末尾
cnt += Dight(p->data); //当到达末尾时,求它的数字的位数
else
cnt += Dight(MOD) - 1; //以MOD(1e9)进位时,当链表未到达结尾时,每个数据域的有9位数
p = p->next;
free(q); //在传值的过程中同时释放空间
}
}
void Clear(LinkList& Head) { //清空链表
LinkList p;
if (Head) {
p = Head;
Head = Head->next;
free(p);
}
}
void Multiply(LinkList& Head, int num) {
LinkList p = Head->next; //指向头结点的后继
ll ans = 0;
do {
ans += p->data * num;
p->data = ans % MOD; //除余
ans /= MOD; //进位
if (p->next == NULL) { //链表已经到末尾,进位还大于0
while (ans > 0) {
LinkList Node = new LNode; //分配内存
Node->data = ans % MOD; //除余
Node->next = NULL;
ans /= MOD; //进位
p->next = Node; //尾插
p = Node;
}
}
p = p->next; //到下个位置
} while (p != NULL); //循环条件(链表是否为空)
}
void factoricial(int num, LinkList& Head) { // 求(num)!的阶乘
for (int i = 2; i <= num; i++) {
Multiply(Head, i); // 调用乘法函数
}
}
void ListShow(LinkList Head) { //输出链表
bool flag = true;
while (Head->next) {
if (flag) { //第一位数不存在前导零
printf("%lld", Head->next->data);
flag = false;
}
else
printf("%09lld", Head->next->data); //由于MOD之后链表数据域存放的数会去掉前导0,所以要补上前导0
Head = Head->next;
}
}
int main() {
LinkList Head = NULL;
LinkList ans = NULL;
InitList(Head); //链表初始化
InitList(ans); //答案链表初始化
Pretreatment(Head); //链表赋予初始值
int num;
cout << "input the num:";
cin >> num;
start = clock(); //开始计时
factoricial(num, Head); //求阶乘
turn(Head, ans); //链表倒置
finish = clock(); //结束记时
double duration = (double)(finish - start) / CLOCKS_PER_SEC; //求计算时间
/* CLOCKS_PER_SEC 是 每秒clock数*/
ListShow(ans);
cout << endl << "used " << duration << " seconds." << endl;
cout << "Digit capacity is " << cnt << endl;
Clear(ans);
return 0;
}