大数运算

来源:互联网 发布:淘宝双11海景房氛围图 编辑:程序博客网 时间:2024/06/05 10:00

1)大正整数的加法

具体思路就是模仿手算的加法,我在这里先将输入的字符串reverse便于操作,最后去掉结果的前置0即可。注意:如果答案就是0,那么需要特殊处理。

大量的测试数据可以 上交至hdu 1002

[cpp] view plaincopy
  1. #include<iostream>  
  2. #include<string>  
  3. #include<algorithm>  
  4. using namespace std;  
  5. int main()  
  6. {  
  7.     int n;  
  8.     cin>>n;  
  9.     int m=0;  
  10.     int l=0;  
  11.     for(int i=1;i<=n;i++)  
  12.     {  
  13.         string s1,s2,s(10000,'0');  
  14.         cin>>s1>>s2;  
  15.         m++;  
  16.         cout<<(l++?"\n":"");  
  17.         reverse(s1.begin(),s1.end());  
  18.         reverse(s2.begin(),s2.end());  
  19.         for(int j=0;j<s1.length();j++)  
  20.         s[j]=s1[j];  
  21.         int temp=0;  
  22.         for(int k=0;k<s2.length();k++)  
  23.         {  
  24.            temp+=s[k]-48+s2[k]-48;  
  25.            s[k]=temp%10+'0';  
  26.            temp/=10;          
  27.         }  
  28.         s[s2.length()]=s[s2.length()]-48+temp+48;   
  29.         reverse(s.begin(),s.end());  
  30.         reverse(s1.begin(),s1.end());  
  31.         reverse(s2.begin(),s2.end());  
  32.         cout<<"Case "<<m<<":"<<endl;  
  33.         cout<<s1<<" + "<<s2<<" = "<<s.substr(s.find_first_not_of('0'))<<endl;  
  34.           
  35.     }  
  36.     return 0;  
  37. }  

(2)大正整数的减法

同样是模拟手算,处理借位。用大的减去小的,最后再判断是否需要添加负号。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <cstring>  
  4. #include <vector>  
  5. #include <algorithm>  
  6. using namespace std;  
  7. int strComp(string &s1,string &s2)  
  8. {  
  9.     int len1=s1.length();  
  10.     int len2=s2.length();  
  11.     if(len1>len2)  
  12.     return 0;  
  13.     else if(len1<len2)  
  14.     return 1;  
  15.     else{  
  16.         if(s1>=s2)  
  17.         return 0;  
  18.         else  
  19.         return 1;  
  20.     }  
  21. }  
  22. int main()  
  23. {  
  24.     string s1,s2;  
  25.     while(cin>>s1>>s2)  
  26.     {  
  27.         string s(10000,'0');  
  28.         bool fgEx=true;  
  29.         if(strComp(s1,s2)==1)  
  30.         {  
  31.             string temp;  
  32.             temp=s1;  
  33.             s1=s2;  
  34.             s2=temp;  
  35.             fgEx=false;  
  36.         }  
  37.         if(s1==s2)  
  38.         {  
  39.             cout<<s1<<" - "<<s2<<" = "<<"0"<<endl;  
  40.             continue;  
  41.         }  
  42.         reverse(s1.begin(),s1.end());  
  43.         reverse(s2.begin(),s2.end());  
  44.         for(int i=0;i<s1.length();i++)  
  45.         s[i]=s1[i];  
  46.         for(int i=0;i<s2.length();i++)  
  47.         {  
  48.             if(s[i]>=s2[i])  
  49.             s[i]=s[i]-'0'-(s2[i]-'0')+'0';  
  50.             else{  
  51.                 s[i+1]=s[i+1]-'0'-1+'0';  
  52.                 s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';  
  53.             }  
  54.         }  
  55.         if(fgEx==false)  
  56.         {  
  57.             reverse(s2.begin(),s2.end());  
  58.             cout<<s2<<" - ";  
  59.             reverse(s1.begin(),s1.end());  
  60.             cout<<s1<<" = ";  
  61.             reverse(s.begin(),s.end());  
  62.             cout<<"-"<<s.substr(s.find_first_not_of('0'))<<endl;  
  63.         }  
  64.         else  
  65.         {  
  66.             reverse(s1.begin(),s1.end());  
  67.             cout<<s1<<" - ";  
  68.             reverse(s2.begin(),s2.end());  
  69.             cout<<s2<<" = ";  
  70.             reverse(s.begin(),s.end());  
  71.             cout<<s.substr(s.find_first_not_of('0'))<<endl;  
  72.         }  
  73.     }  
  74.     return 0;  
  75.       
  76. }   
(3)大正整数乘法

还是模拟手算,第一个字符串的第i位乘以第二个字符串的第j位一定是结果的第i+j位,如果i+j已经有值,直接加上去就OK,别忘了处理进位。

这样的算法的复杂度是O(n2).利用FFT可以将算法优化到O(nlogn),关于FFT的实现在此不再赘述,可以参考算法导论或者   http://www.cnblogs.com/lsx54321/archive/2012/07/20/2601632.html。同样可提交至poj 2389。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <cstring>  
  4. #include <vector>  
  5. #include <algorithm>  
  6. using namespace std;  
  7. int main()  
  8. {  
  9.     string s1,s2;  
  10.     while(cin>>s1>>s2)  
  11.     {  
  12.         string s(1000,'0');  
  13.         reverse(s1.begin(),s1.end());  
  14.         reverse(s2.begin(),s2.end());  
  15.         for(int i=0;i<s1.length();i++)  
  16.         for(int j=0;j<s2.length();j++)  
  17.         {  
  18.             int temp=(s1[i]-'0')*(s2[j]-'0');  
  19.             s[i+j+1]=s[i+j+1]-'0'+(s[i+j]-'0'+temp)/10+'0';  
  20.             s[i+j]=(s[i+j]-'0'+temp)%10+'0';  
  21.         }  
  22.         reverse(s.begin(),s.end());  
  23.         if(s.find_first_not_of('0')==string::npos)  
  24.         cout<<"0"<<endl;  
  25.         else  
  26.         cout<<s.substr(s.find_first_not_of('0'))<<endl;  
  27.     }  
  28.     return 0;  
  29. }  
(4)大整数除法

我们将除法看作是减法来处理,用被减数不断的减去减数,记录减的次数即是商的值。但是我们当然不能一个一个减,因为如果有10000000/1这种情况不是要减到猴年马月。

我们可以记录被减数和减数的位数之差len,将减数扩大10的len倍。然后依次去减,一旦被减数小于减数时,将减数减小10倍,直至到原值。依次循环,去掉前置0,得出结果。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <string>  
  3. #include <cstring>  
  4. #include <vector>  
  5. #include <algorithm>  
  6. using namespace std;  
  7. int strComp(string &s1,string &s2)  
  8. {  
  9.     int len1=s1.length();  
  10.     int len2=s2.length();  
  11.     if(len1>len2)  
  12.     return 0;  
  13.     else if(len1<len2)  
  14.     return 1;  
  15.     else{  
  16.         if(s1>=s2)  
  17.         return 0;  
  18.         else  
  19.         return 1;  
  20.     }  
  21. }  
  22. string Sub(string s1,string s2)  
  23. {  
  24.         if(strComp(s1,s2)==1)  
  25.         return "-1";  
  26.         reverse(s1.begin(),s1.end());  
  27.         reverse(s2.begin(),s2.end());  
  28.         string s(1000,'0');  
  29.         for(int i=0;i<s1.length();i++)  
  30.         s[i]=s1[i];  
  31.         for(int i=0;i<s2.length();i++)  
  32.         {  
  33.             if(s[i]>=s2[i])  
  34.             s[i]=s[i]-'0'-(s2[i]-'0')+'0';  
  35.             else{  
  36.                 s[i+1]=s[i+1]-'0'-1+'0';  
  37.                 s[i]=s[i]-'0'+10-(s2[i]-'0')+'0';  
  38.             }  
  39.         }  
  40.         reverse(s.begin(),s.end());  
  41.         if(s.find_first_not_of('0')==string::npos)  
  42.         return "0";  
  43.         else  
  44.         return s.substr(s.find_first_not_of('0'));  
  45. }  
  46. int main()  
  47. {  
  48.     string s1,s2;  
  49.     while(cin>>s1>>s2)  
  50.     {  
  51.         string s(1000,'0');  
  52.         if(strComp(s1,s2)==1)  
  53.         {  
  54.           cout<<"0"<<endl;  
  55.           continue;  
  56.         }  
  57.         int len1=s1.length();  
  58.         int len2=s2.length();  
  59.         int dis=len1-len2;  
  60.         for(int i=0;i<dis;i++)  
  61.         s2+='0';  
  62.         string ans(1000,'0');  
  63.         while(dis>=0)  
  64.         {  
  65.               int sum=0;  
  66.               string temp;  
  67.               while((temp=Sub(s1,s2))!="-1")  
  68.               {  
  69.                   sum++;  
  70.                   s1=temp;  
  71.               }   
  72.               ans[ans.length()-dis-1]=sum+'0';  
  73.               dis--;  
  74.               s2=s2.substr(0,len2+dis);  
  75.         }  
  76.         if(ans.find_first_not_of('0')==string::npos)  
  77.         cout<<"0"<<endl;  
  78.         else{  
  79.         string res=ans.substr(ans.find_first_not_of('0'));  
  80.         cout<<res<<endl;  
  81.         }  
  82.     }  
  83.     return 0;  
  84. }  

原创粉丝点击