题目很简单,就是输入一个N,求N的阶乘。
这个题目是一个大数乘小数的问题,例如N! =(N-1)! * N,这里,(N-1)!为大数,表示为字符串的形式,N为小数,表示为int的形式。这道题的重点就是写一个函数实现一个大数乘小数。
一开始我的做法是大数和小数全部作为字符串处理,类似于小学时的基本的竖式乘法来计算,这样的话时间复杂度会非常高,设大数有x位数字,小数有y位数,需要有xy次访问,并且每次还需要进行一次大数加法运算,时间复杂度实在太高,代码提交上去肯定会超时的。
大数×小数的基本思想是:我们小学时候的乘法竖式运算将每个数都一位一位的进行乘法运算,这里我们将小数看成一个整体。例如7231(大数,表示为字符串)×39(小数),设置一个变量carry表示进位。result字符串表示结果,初始化为空串
carry=0,遍历大数的每一位:
1×39+carry=39 carry=39/10=3 39%10=9,result='9'+result=9
3×39+carry=120 carry=120/10=12 120%10=0 result='0'+result=09
2×39+carry=90 carry=9 result=009
7×39+carry=282 carry=28 result=2009
此时大数的每一位遍历完成,carry=28,result="28"+result=282009得到结果。
附上HDOJ1042的代码,BigInt类封装了大整数
#include<iostream>
#include<cstdio>
using namespace std;
//#define DEBUG
void calFactorial(int N);
string intToString(int a);
class BigInt{
public:
BigInt(){}
BigInt(int value){
setnum(value);
}
void operator*=(int& b);
void print(){
for(int i=start;i<end;i++){
cout<<num[i];
}
cout<<endl;
}
void setnum(int value){
start=end=numsize-1;
int tmp;
while(value!=0){
tmp=value%10;
num[--start]=tmp+'0';
value=value/10;
}
}
static const int numsize=100000;
private:
char num[numsize];
int start;//start为起始数字下标
int end;//(end-1)为最后一个数字下标
};
void BigInt::operator*=(int& b){
int carry=0;
int bigint_p=end-1;
for(;bigint_p!=start-1;bigint_p--){
int tmp_data=(num[bigint_p]-'0')*b+carry;
carry=tmp_data/10;
num[bigint_p]=(tmp_data%10)+'0';
}
bigint_p++;
//cout<<"carry="<<carry<<endl;
while(carry!=0){
int tmp_data=carry%10;
num[--bigint_p]=tmp_data+'0';
carry=carry/10;
}
start=bigint_p;
}
int N;
int main(){
while(scanf("%d",&N)!=EOF){
calFactorial(N);
}
}
void calFactorial(int N){
#ifdef DEBUG
//cout<<"N="<<Nstring<<endl;
#endif
BigInt result;
BigInt mul_num;
result.setnum(1);
for(int i=2;i<=N;i++){
result*=i;//大数乘小数,结果保存在大数中
//cout<<"i="<<i<<endl;
}
result.print();
}