Nguồn đề bài: BIGNUM
1. Đề bài BIGNUM spoj
Cho hai số nguyên dương A và B ( A & B có không quá 1000 chữ số )
Yêu cầu
Tính A + B, A – B, A * B
Khi kết quả là 0 các bạn phải in ra 0, nếu in -0 là sai
Các chữ số 0 không có nghĩa ở đầu không được in ra. VD 013 thì phải in ra là 13, chữ số 0 ở đầu không có nghĩa vì cách chấm ở đây là so sánh 2 FILE kết quả
Input
Dòng 1: số nguyên A
Dòng 2: số nguyên B
Output
Dòng 1: Kết quả A + B
Dòng 2: Kết quả A – B
Dòng 3: Kết quả A * B
Example
Input:
10
11
Output:
21
-1
110
2. Code tham khảo BIGNUM spoj
a. Code BIGNUM pascal
{$MODE OBJFPC} Const digit=8; maxN=301; base=100000000; Type BigNum=array[0..maxN] of Int64; ll=LongInt; Var s1,s2,Res : AnsiString; a1,a2 : BigNum; ex : boolean; Function max(a,b:Int64):Int64; Begin if a>b then max:=a else max:=b; End; Procedure CoverBigNum(s:AnsiString;var a:BigNum); Var sn,i,j: ll; Begin Fillchar(a,sizeof(a),0); If s='0' then exit; sn:=(length(s)+digit-1) div digit; While length(s)<sn*digit do s:='0'+s; j:=length(s); a[0]:=sn; For i:=1 to sn do begin val(copy(s,j-digit+1,digit),a[i]); j:=j-digit; end; End; Procedure CoverNumBer(a:BigNum; Var Res: AnsiString); Var s:AnsiString; i:ll; Begin If a[0]=0 then begin res:='0'; exit; end; res:=''; For i:=1 to a[0] do begin str(a[i],s); while length(s)<digit do s:='0'+s; res:=s+res; end; While res[1]='0' do delete(res,1,1); End; Operator =(a,b: BigNum)bang: Boolean; Var x,y: AnsiString; Begin CoverNumBer(a,x); CoverNumBer(b,y); exit(x=y); End; Operator +(var a,b:BigNum)cong:BigNum; Var i :ll; num,nho:Int64; Begin If (a[0]=0) or (b[0]=0) then begin If a[0]=0 then cong:=b else cong:=a; exit; end; cong[0]:=max(a[0],b[0]); nho:=0; For i:=1 to cong[0] do begin num:=a[i]+b[i]+nho; cong[i]:=num mod base; nho:=num div base; end; If nho>0 then begin Inc(cong[0]); cong[cong[0]]:=nho; end; End; Operator -(a,b:BigNum)tru:BigNum; Var tmp: BigNum; i :ll; num,nho:Int64; Begin If a=b then begin FillChar(tru,SizeOf(tru),0); exit; end; If ex then begin tmp:=a; a:=b; b:=tmp; end; tru[0]:=max(a[0],b[0]); nho:=0; For i:=1 to tru[0] do begin num:=a[i]-b[i]-nho; If num<0 then begin nho:=1; num:=num+base; end else nho:=0; tru[i]:=num mod base; end; End; Operator *(a,b:BigNum)nhan:BigNum; Var i,j:ll; x, nho:Int64; S: AnsiString; Begin Fillchar(nhan,sizeof(nhan),0); If (a[0]=0) or (b[0]=0) then exit; nhan[0]:=a[0]+b[0]-1; For i:=1 to a[0] do For j:=1 to b[0] do nhan[i+j-1]:=nhan[i+j-1]+a[i]*b[j]; nho:=0; For i:=1 to nhan[0] do begin x:=nhan[i]+nho; nho:=x div base; nhan[i]:=x mod base; end; If nho>0 then begin inc(nhan[0]); nhan[nhan[0]]:=nho; end; End; Procedure Enter; Begin ReadLn(s1); ReadLn(s2); ex:=(length(s1)<length(s2)) or ((length(s1)=length(s2)) and (s1<s2)); End; Procedure Main; Var x:BigNum; Begin CoverBigNum(s1,a1); CoverBigNum(s2,a2); CoverNumBer(a1+a2,Res); WriteLn(Res); CoverNumBer(a1-a2,Res); If ex then Write('-'); WriteLn(Res); CoverNumBer(a1*a2,Res); WriteLn(Res); End; BEGIN Enter; Main; END.
b. Code BIGNUM c++
#include<iostream> #include<string> using namespace std; string add(string a, string b) { string res=""; while(a.length() < b.length()) a="0"+a; while(b.length() < a.length()) b="0"+b; int carry=0; for(int i=a.length()-1;i>=0;i--) { int tmp=a[i]-48 + b[i]-48 + carry; carry=tmp/10; tmp=tmp%10; res=(char)(tmp+48)+res; } if(carry>0) res="1"+res; return res; } string sub(string a, string b) { string res=""; while(a.length() < b.length()) a="0"+a; while(b.length() < a.length()) b="0"+b; bool neg=false; if(a<b) { swap(a,b); neg=true; } int borrow=0; for(int i=a.length()-1; i>=0;i--) { int tmp=a[i]-b[i]-borrow; if(tmp<0) { tmp+=10; borrow=1; } else borrow=0; res=(char)(tmp%10 + 48) + res; } while(res.length()>1 && res[0]=='0') res.erase(0,1); if(neg) res="-"+res; return res; } string mul(string a, string b) { string res=""; int n=a.length(); int m=b.length(); int len=n+m-1; int carry=0; for(int i=len;i>=0;i--) { int tmp=0; for(int j=n-1;j>=0;j--) if(i-j<=m && i-j>=1) { int a1=a[j]-48; int b1=b[i-j-1]-48; tmp+=a1*b1; } tmp+=carry; carry=tmp/10; res=(char)(tmp%10 + 48)+res; } while(res.length()>1 && res[0]=='0') res.erase(0,1); return res; } int main() { //freopen("in.txt","r",stdin); string a, b; cin>>a>>b; cout<<add(a,b)<<endl; cout<<sub(a,b)<<endl; cout<<mul(a,b); }
c. Code BIGNUM c++ tối ưu
Code này không dùng để submit lên spoj, nhưng bạn có thể dùng nó để xử lí các bài toán khác, nó rất tối ưu.
Mình xin phép chia sẻ lại của anh Nguyễn Tiến Trung Kiên
#include <stdio.h> #include <assert.h> #include <vector> #include <iostream> #include <algorithm> using namespace std; #define long long long #define f1(i,n) for (int i=1; i<=n; i++) #define f0(i,n) for (int i=0; i<n; i++) typedef vector<int> vi; const int BASE=10000; void fix(vi &a){ a.push_back(0); f0(i,a.size()-1) { a[i+1]+=a[i]/BASE; a[i]%=BASE; if (a[i]<0) { a[i]+=BASE; a[i+1]--; } } while (a.size()>=2 && a.back()==0) a.pop_back(); } void operator += (vi &a, const vi &b) { a.resize(max(a.size(), b.size())); f0(i,b.size()) a[i]+=b[i]; fix(a); } vi operator * (const vi &a, const vi &b){ vi c(a.size()+b.size()); f0(i,a.size()) f0(j,b.size()) c[i+j]+=a[i]*b[j]; return fix(c), c; } vi to_vi(int x) // x<BASE { return vi(1,x); } void operator -= (vi &a, const vi &b) { f0(i,b.size()) a[i]-=b[i]; fix(a); } void operator *= (vi &a, int x) // x<BASE { f0(i,a.size()) a[i]*=x; fix(a); } vi operator + (vi a, const vi &b) { a+=b; return a; } vi operator - (vi a, const vi &b) { a-=b; return a; } vi operator * (vi a, int x) // x<BASE { a*=x; return a; } bool operator < (const vi &a, const vi &b){ if (a.size() != b.size()) return a.size()<b.size(); for (int i=a.size()-1; i>=0; i--) if (a[i]!=b[i]) return a[i]<b[i]; return false; } void divide(const vi &a, int x, vi &q, int &r) { q.clear(); r=0; for (int i=a.size()-1; i>=0; i--) { r=r*BASE+a[i]; q.push_back(r/x); r%=x; } reverse(q.begin(), q.end()); fix(q); } vi operator / (const vi &a, int x) { vi q; int r; divide(a, x, q, r); return q; } int operator % (const vi &a, int x) { vi q; int r; divide(a, x, q, r); return r; } istream& operator >> (istream& cin, vi &a){ string s; cin >> s; a.clear(); a.resize(s.size()/4+1); f0(i,s.size()) { int x = (s.size()-1-i)/4; // <- log10(BASE)=4 a[x]=a[x]*10+(s[i]-'0'); } return fix(a), cin; } ostream& operator << (ostream& cout, const vi &a){ printf("%d", a.back()); for (int i=(int)a.size()-2; i>=0; i--) printf("%04d", a[i]); return cout; } void test_fib(int n){ vi a=to_vi(1), b=to_vi(1); f1(i,n/2) { a+=b; b+=a; cout << "F[" << i*2+1 << "]=" << a << endl; cout << "F[" << i*2+2 << "]=" << b << endl; } } void test_fact(int n){ vi P=to_vi(1); f1(i,n) { P*=i; cout << i << "!= " << P << endl; } } void test_divide(){ vi a; int x; for (;;){ cout << "Input a big integer and a small integer (<10000)" << endl; if (cin >> a >> x); else break; cout << "a=" << a << " x=" << x << endl; vi q=a/x; int r=a%x; cout << "a/x=" << q << "; a%x=" << r << endl; vi a0 = q*to_vi(x)+to_vi(r); assert(a0==a && !(a0<a) && !(a0>a)); } } main(){ cout << "Press Enter to run test_fib()" << endl; cin.ignore(1); test_fib(100); cout << "Press Enter to run test_fact()" << endl; cin.ignore(1); test_fact(100); cout << "Press Enter to run test_divide()" << endl; cin.ignore(1); test_divide(); }