您的位置:首页 > 编程语言 > C语言/C++

[acm 1001] c++ 大数加法 乘法 幂

2015-04-12 10:09 435 查看
北大的ACM 1001

poj.org/problem?id=1001

代码纯手动编写 - -

#include <iostream>
#include <cstdio>
#include <cstring>

class BigNumber
{
struct BigNumberNode
{
BigNumberNode():n(0), prev(NULL), next(NULL){}
BigNumberNode(int N):n(N), prev(NULL), next(NULL){}

int n;
BigNumberNode *prev, *next;
};

BigNumberNode *head, *tail;
int dot_before; // 小数点之前的数量
int dot_later;  // 小数点之后的数量

void InsertNodeAtBegin(int n)
{
BigNumberNode *new_node = new BigNumberNode(n);
if(head != NULL)
{
head->prev = new_node;
new_node->prev = NULL;
new_node->next = head;
head = new_node;
}
else
{
head = new_node;
tail = new_node;
new_node->prev = NULL;
new_node->next = NULL;
}
}

void InsetNodeAtEnd(int n)
{
BigNumberNode *new_node = new BigNumberNode(n);
if(head != NULL)
{
new_node->prev = tail;
new_node->next = NULL;
tail->next = new_node;
tail = new_node;
}
else
{
head = new_node;
tail = new_node;
new_node->prev = NULL;
new_node->next = NULL;
}
}

void DeleteBegin()
{
if(head != NULL)
{
if (head->next != NULL)
{
BigNumberNode* temp = head->next;
delete head;
head = temp;
temp->prev = NULL;

if (dot_before != 0)
{
dot_before--;
}
else
{
dot_later--;
}
}
else
{
Free();
}
}
}

void DeleteEnd()
{
if(tail != NULL)
{
if (tail->prev != NULL)
{
BigNumberNode* temp = tail->prev;
delete tail;
tail = temp;
temp->next = NULL;

if (dot_later != 0)
{
dot_later--;
}
else
{
dot_before--;
}
}
else
{
Free();
}
}
}

// 去除前/后导 0
// 去除前/后导 0
void ClearZeros()
{
// 后导 0
BigNumberNode *p;

int max_limit = dot_later;
for(int i = 0; i < max_limit; i++)
{
p = tail;

if(p->n == 0)
{
DeleteEnd();
}
else
{
break;
}
}

// 前导 0
max_limit = dot_before;
for(int i = 0; i < max_limit; i++)
{
p = head;

if(p->n == 0)
{
DeleteBegin();
}
else
{
break;
}
}
}

BigNumber Mul(const BigNumber &Scale)
{
const BigNumber &a = *this, &b = Scale;
BigNumber sum_big_number;

int sum = 0;
int reserve = 0;
int tag = 0;

BigNumberNode *pa = a.tail, *pb = b.tail;

//    xxxxxx a
//       xxx b
// --------- Mul
//    xxxxxx
//   xxxxxx
//  xxxxxx
// --------- Add
// xxxxxxxxx

while(pb)
{
BigNumber temp_big_number;
pa = a.tail;
while(pa)
{
sum = pa->n * pb->n + reserve;
reserve = sum / 10;
temp_big_number.InsertNodeAtBegin(sum - reserve * 10);
temp_big_number.dot_before++;
pa = pa->prev;
}

if (reserve)
{
temp_big_number.InsertNodeAtBegin(reserve);
temp_big_number.dot_before++;
reserve = 0;
}

for (int i = 0; i < tag; i++)
{
temp_big_number.InsetNodeAtEnd(0);
temp_big_number.dot_before++;
}

sum_big_number += temp_big_number;

tag++;
pb = pb->prev;
}

sum_big_number.dot_later = a.dot_later + b.dot_later;

if (sum_big_number.dot_before > sum_big_number.dot_later)
{
sum_big_number.dot_before -= sum_big_number.dot_later;
}
else
{
int temp = sum_big_number.dot_later - sum_big_number.dot_before;
sum_big_number.dot_before = 0;
for (int i = 0; i < temp; i++)
{
sum_big_number.InsertNodeAtBegin(0);
}
}

sum_big_number.ClearZeros();

return sum_big_number;
}

public:

~BigNumber()
{
Free();
}

BigNumber(): head(NULL), tail(NULL), dot_before(0), dot_later(0)
{
}

BigNumber(const char *Str): head(NULL), tail(NULL), dot_before(0), dot_later(0)
{
Free();
AdaptFormString(Str);
}

BigNumber(const BigNumber& Source): head(NULL), tail(NULL), dot_before(0), dot_later(0)
{
*this = Source;
}

const BigNumber& operator=(const BigNumber& Source)
{
if (this != &Source)
{
this->Free();

BigNumberNode *p = Source.head;
while(p)
{
this->InsetNodeAtEnd(p->n);
p = p->next;
}

this->dot_before = Source.dot_before;
this->dot_later = Source.dot_later;
}

return *this;
}

BigNumber operator+(const BigNumber Addend)
{
const BigNumber &a = *this, &b = Addend;
BigNumber new_number;

BigNumberNode *pa, *pb;
int sum, remain, odd;
int reserve = 0;
bool is_dot_before_longer_is_a; // 帮助标记小数点之前的部分
bool is_dot_later_longer_is_a;

// 小数点之后
if(a.dot_later > b.dot_later)
{
pa = a.tail;
pb = b.tail;
remain = b.dot_later;
odd = a.dot_later - b.dot_later;
is_dot_later_longer_is_a = true;
}
else
{
pa = b.tail;
pb = a.tail;
remain = a.dot_later;
odd = b.dot_later - a.dot_later;
is_dot_later_longer_is_a = false;
}

for (int i = 0; i < odd; i++)
{
new_number.InsertNodeAtBegin(pa->n);
new_number.dot_later++;
pa = pa->prev;
}

for (int i = 0; i < remain; i++)
{
sum = pa->n + pb->n + reserve;
reserve = sum / 10;
new_number.InsertNodeAtBegin(sum - reserve * 10);
new_number.dot_later++;
pa = pa->prev;
pb = pb->prev;
}

// 小数点之前
if(a.dot_before > b.dot_before)
{
remain = b.dot_before;
odd = a.dot_before - b.dot_before;
is_dot_before_longer_is_a = true;
}
else
{
remain = a.dot_before;
odd = b.dot_before - a.dot_before;
is_dot_before_longer_is_a = false;
}

BigNumberNode *temp; // 用于交换 pa pb
if (is_dot_before_longer_is_a && is_dot_later_longer_is_a
|| !is_dot_before_longer_is_a && !is_dot_later_longer_is_a)
{
// 不用交换
}
else
{
temp = pa;
pa = pb;
pb = temp;
}

for (int i = 0; i < remain; i++)
{
sum = pa->n + pb->n + reserve;
reserve = sum / 10;
new_number.InsertNodeAtBegin(sum - reserve * 10);
new_number.dot_before++;
pa = pa->prev;
pb = pb->prev;
}

for (int i = 0; i < odd; i++)
{
sum = pa->n + reserve;
reserve = sum / 10;
new_number.InsertNodeAtBegin(sum - reserve * 10);
new_number.dot_before++;
pa = pa->prev;
}

// 检测是否最后还有一位
if (reserve)
{
new_number.InsertNodeAtBegin(reserve);
new_number.dot_before++;
reserve = 0;
}

new_number.ClearZeros();

return new_number;
}

BigNumber operator*(const BigNumber& Scale)
{
return Mul(Scale);
}

BigNumber& operator+=(const BigNumber Addend)
{
BigNumber &a = *this;
const BigNumber &b = Addend;

BigNumberNode *pa = a.tail, *pb = b.tail;
int sum = 0, remain = 0, odd = 0;
int reserve = 0;

// 小数点之后
if(a.dot_later > b.dot_later)
{
remain = b.dot_later;
odd = a.dot_later - b.dot_later;

for (int i = 0; i < odd; i++)
{
pa = pa->prev;
}
}
else
{
remain = a.dot_later;
odd = b.dot_later - a.dot_later;

char *odd_n = new char[odd];
for (int i = 1; i <= odd; i++)
{
odd_n[odd - i] = pb->n;
pb = pb->prev;
}

for (int i = 0; i < odd; i++)
{
a.InsetNodeAtEnd(odd_n[i]);
a.dot_later++;
}
delete odd_n;
}

for (int i = 0; i < remain; i++)
{
sum = pa->n + pb->n + reserve;
reserve = sum / 10;
pa->n = sum - reserve * 10;

pa = pa->prev;
pb = pb->prev;
}

// 小数点之前
if(a.dot_before > b.dot_before)
{
remain = b.dot_before;
odd = a.dot_before - b.dot_before;

for (int i = 0; i < remain; i++)
{
sum = pa->n + pb->n + reserve;
reserve = sum / 10;
pa->n = sum - reserve * 10;

pa = pa->prev;
pb = pb->prev;
}

for (int i = 0; i < odd; i++)
{
sum = pa->n + reserve;
reserve = sum / 10;
pa->n = sum - reserve * 10;

pa = pa->prev;
}
}
else
{
remain = a.dot_before;
odd = b.dot_before - a.dot_before;

for (int i = 0; i < remain; i++)
{
sum = pa->n + pb->n + reserve;
reserve = sum / 10;
pa->n = sum - reserve * 10;

pa = pa->prev;
pb = pb->prev;
}

for (int i = 0; i < odd; i++)
{
sum = pb->n + reserve;
reserve = sum / 10;
a.InsertNodeAtBegin(sum - reserve * 10);
a.dot_before++;
pb = pb->prev;
}

}

// 检测是否最后还有一位
if (reserve)
{
a.InsertNodeAtBegin(reserve);
a.dot_before++;
}

a.ClearZeros();

return *this;
}

void _Print()
{
if(dot_before == 0 && dot_later == 0)
{
putchar('0');
}
else if (dot_later == 0)
{
BigNumberNode *p = head;

while(p)
{
putchar(p->n + '0');
p = p->next;
}
}
else
{
BigNumberNode *p = head;

for(int i = 0; i < dot_before; i++)
{
putchar(p->n + '0');
p = p->next;
}

putchar('.');

while(p)
{
putchar(p->n + '0');
p = p->next;
}
}
}

void PrintString()
{
if(dot_before == 0 && dot_later == 0)
{
putchar('0');
}
else if (dot_later == 0)
{
char *temp = new char[dot_before + dot_later + 2], *ptemp = temp;
BigNumberNode *p = head;

while(p)
{
*ptemp = p->n + '0';
ptemp++;
p = p->next;
}
*ptemp = 0;

std::cout<<temp<<'\n';
delete[] temp;
}
else
{
char *temp = new char[dot_before + dot_later + 2], *ptemp = temp;
BigNumberNode *p = head;

for(int i = 0; i < dot_before; i++)
{
*ptemp = p->n + '0';
ptemp++;
p = p->next;
}

*ptemp = '.';
ptemp++;

while(p)
{
*ptemp = p->n + '0';
ptemp++;
p = p->next;
}
*ptemp = 0;

std::cout<<temp<<'\n';
delete[] temp;
}
}

void Free()
{
BigNumberNode *p = head, *temp;

while(p)
{
temp = p;
p = p->next;
delete temp;
}

head = NULL;
tail = NULL;
dot_before = 0;
dot_later = 0;
}

// 从字符串建立数据,未加入错误检测
void AdaptFormString(const char *Str)
{
Free();

const char *pc = Str;

// 小数点之前
while(*pc)
{
if(*pc != '.') // 0 ~ 9
{
InsetNodeAtEnd(*pc - '0');
dot_before++;
pc++;
}
else // 小数点之后
{
pc++;
while(*pc)
{
InsetNodeAtEnd(*pc - '0');
dot_later++;
pc++;
}
break;
}
}

ClearZeros();
}

};

// 自顶向下的动态规划
BigNumber* BigNumberPowUP(BigNumber* result[], int pow)
{
if( result[pow] )
{
return result[pow];
}
else
{
int left = pow / 2;
int right = pow - left;

result[left] = BigNumberPowUP(result, left);
result[right] = BigNumberPowUP(result, right);

result[pow] = new BigNumber((*result[left]) * (*result[right]));

return result[pow];
}
}

BigNumber BigNumberPow(const BigNumber& R, int pow)
{
BigNumber *result[26] = {0};

result[1] = new BigNumber(R);

BigNumberPowUP(result, pow);

BigNumber Result = *result[pow];

for (int i = 0; i <= pow; i++)
{
delete result[i];
}

return Result;
}

int main(void)
{
char Rstr[10];
int n;

while(scanf("%s%d", Rstr, &n) != EOF)
{
BigNumber result = BigNumberPow(Rstr, n);
result.PrintString();
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: