ACM专题 - 高精度题型总结(用string类处理高精度问题)

摘要

最近打了不少高精度有关的机试题,在这里总结一下。

高精度的运算类型大致可以分为除(/)、取模(%)、加(+)、减(-)、和乘(×)五种。其中除和取模两者是从高位向低位计算,而加减乘三者是从低位向高位计算。

高精度除法

经典例题:POJ1220 Number Base Convertion

原题:

NUMBER BASE CONVERSION

Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 6604 Accepted: 3035

Description

Write a program to convert numbers in one base to numbers in a second base. There are 62 different digits:
{ 0-9,A-Z,a-z }
HINT: If you make a sequence of base conversions using the output of one conversion as the input to the next, when you get back to the original base, you should get the original number.

Input

The first line of input contains a single positive integer. This is the number of lines that follow. Each of the following lines will have a (decimal) input base followed by a (decimal) output base followed by a number expressed in the input base. Both the input base and the output base will be in the range from 2 to 62. That is (in decimal) A = 10, B = 11, ..., Z = 35, a = 36, b = 37, ..., z = 61 (0-9 have their usual meanings).

Output

The output of the program should consist of three lines of output for each base conversion performed. The first line should be the input base in decimal followed by a space then the input number (as given expressed in the input base). The second output line should be the output base followed by a space then the input number (as expressed in the output base). The third output line is blank.

Sample Input

8
62 2 abcdefghiz
10 16 1234567890123456789012345678901234567890
16 35 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 23 333YMHOUE8JPLT7OX6K9FYCQ8A
23 49 946B9AA02MI37E3D3MMJ4G7BL2F05
49 61 1VbDkSIMJL3JjRgAdlUfcaWj
61 5 dl9MDSWqwHjDnToKcsWE1S
5 10 42104444441001414401221302402201233340311104212022133030

Sample Output

62 abcdefghiz
2 11011100000100010111110010010110011111001001100011010010001

10 1234567890123456789012345678901234567890
16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2

16 3A0C92075C0DBF3B8ACBC5F96CE3F0AD2
35 333YMHOUE8JPLT7OX6K9FYCQ8A

35 333YMHOUE8JPLT7OX6K9FYCQ8A
23 946B9AA02MI37E3D3MMJ4G7BL2F05

23 946B9AA02MI37E3D3MMJ4G7BL2F05
49 1VbDkSIMJL3JjRgAdlUfcaWj

49 1VbDkSIMJL3JjRgAdlUfcaWj
61 dl9MDSWqwHjDnToKcsWE1S

61 dl9MDSWqwHjDnToKcsWE1S
5 42104444441001414401221302402201233340311104212022133030

5 42104444441001414401221302402201233340311104212022133030
10 1234567890123456789012345678901234567890

Source

Greater New York 2002

题目大意:

输入以'0'~'9'、'A-Z'、'a~z'构成的高精度整型字符串,同时给出当前进制N和目标进制M。要求将高精度数值转为M进制数并输出。

AC代码:

#include <iostream>
#include <cstring>
#include <string>
#include <vector>
using namespace std;
#define ms(Arr) memset(Arr,0,sizeof(Arr))
#define INF 0x3f3f3f3f

//19:30~20:32
//AC 180K 0MS C++
const int MAXN = 1e3;
int dividend[MAXN+5];
int len1;

//convert char to int
int ctoi(char c){
    if(c>='0'&&c<='9') return c-'0';
    else if(c>='A'&&c<='Z') return c-'A'+10;
    else return c-'a'+36;
}
//convert int to char
char itoc(int i){
    if(i<=9) return '0'+i;
    else if(i<=35) return 'A'+i-10;
    else return 'a'+i-36;
}
//convert string to int array
void StrToArr(string s){
    len1 = s.length();
    for(int i=0;i<len1;++i){
        dividend[len1-1-i] = ctoi(s[i]);
    }
}
//print int array (即dividend)
//void Print(int A[],int len){
//    for(int i=len-1;i>=0;--i) cout<<A[i]<<" "; cout<<endl;
//}
//短除法,直接实现从K1转K2
string Trans(int K1,int K2,string M){
    int mod;
    string ans("");
    StrToArr(M);
//    Print(dividend,len1);
    while(len1){
        for(int i=len1-1;i>=0;--i){
            mod = dividend[i]%K2;
            dividend[i] /= K2;
            if(i>=1) dividend[i-1] += mod*K1;
        }
        for(;len1 && dividend[len1-1]==0;--len1);
        ans = string(1,itoc(mod))+ans;
//        Print(dividend,len1);
//        cout<<ans<<endl;
    }
    return ans;
}

int main(){
    //freopen("input.txt","r",stdin);
    string M,ans;
    int t,K1,K2;
    cin>>t;
    while(t--){
        cin>>K1>>K2>>M;
        ms(dividend);
        len1 = 0;
        ans = Trans(K1,K2,M);
        cout<<K1<<" "<<M<<endl;
        cout<<K2<<" "<<ans<<endl<<endl;
    }
    return 0;
}

高精度取模

经典例题:Bailian2925 大整数的因子

原题:

2925:大整数的因子

总时间限制: 1000ms                  内存限制: 65536kB

描述

已知正整数k满足2<=k<=9,现给出长度最大为30位的十进制非负整数c,求所有能整除c的k。

输入

一个非负整数c,c的位数<=30。

输出

若存在满足 c%k == 0 的k,从小到大输出所有这样的k,相邻两个数之间用单个空格隔开;若没有这样的k,则输出"none"。

样例输入

30

样例输出

2 3 5 6 

AC代码: 

#include <iostream>
#include <string>
#include <vector>
using namespace std;

//7:41~8:04 23min
//AC 504kB 3MS C++11
char itoc(int i){ return i+'0'; }
int ctoi(char c){ return c-'0'; }
int mod(string s,int k){ //calc s%k, return a int
    int len = s.length();
    int sum = 0;
    for(int i=0;i<len;++i){
        sum = (ctoi(s[i])+sum)%k;
        if(i!=len-1) sum = (sum*10)%k;       
    }
    return sum;   
}

int main(){
    string c;
    vector<int> vec;
    while(cin>>c){
        if(c=="-1") break;
        vec.clear();
        for(int k=2;k<=9;++k){
            if(!mod(c,k)) vec.push_back(k);
        }
        for(int i=0;i<vec.size();++i){
            if(i!=vec.size()-1) cout<<vec[i]<<" ";
            else cout<<vec[i]<<endl;
        }
        if(!vec.size()) cout<<"none"<<endl;
    }
    return 0;
}

高精度加法

经典例题:a+b(华中科技大学复试上机题)

原题:

题目描述

实现一个加法器,使其能够输出a+b的值。

输入描述:

输入包括两个数a和b,其中a和b的位数不超过1000位。

输出描述:

可能有多组测试数据,对于每组数据,输出a+b的值。

示例1

输入

2 6
10000000000000000000 10000000000000000000000000000000

输出

​8
10000000000010000000000000000000

AC代码: 

#include <iostream>
#include <string>
using namespace std;

//6:58~7:14 16min
//AC 480kB 3MS C++11
void Swap(string &a,string &b){
    string temp = b;
    b = a;
    a = temp;
}
char itoc(int i){ return i+'0'; }
int ctoi(char c){ return c-'0'; }

int main(){
    string a,b,ans;
    int len1,len2,sum;
    while(cin>>a>>b){
        if(a.length()<b.length()) Swap(a, b); //Make sure a is not shorter than b
        len1 = a.length();
        len2 = b.length();
        ans = string("");
        sum = 0;
        int i=len1-1,j=len2-1;
        for(;j>=0;--i,--j){
            sum = ctoi(a[i])+ctoi(b[j])+sum;
            ans = string(1,itoc(sum%10))+ans;
            sum /= 10;
        }
        for(;i>=0;--i){
            sum = ctoi(a[i])+sum;
            ans = string(1,itoc(sum%10))+ans;
            sum /= 10;
        }
        cout<<ans<<endl;
    }
    return 0;
}

高精度减法

和高精度加法类似,代码参考加法。(略)

高精度乘法

经典例题:N的阶乘(清华大学复试上机题)

原题:

题目描述

输入一个正整数N,输出N的阶乘。

输入描述:

正整数N(0<=N<=1000)

输出描述:

输入可能包括多组数据,对于每一组输入数据,输出N的阶乘

示例1

输入

4
5
15

输出

24
120
1307674368000

AC代码: 

#include <iostream>
#include <string>
using namespace std;

//7:16~7:25 9min
//AC 504kB 91MS C++11
char itoc(int i){ return i+'0'; }
int ctoi(char c){ return c-'0'; }
string multiply(string s,int n){ //calc s*n, return a string
    string ans("");
    int len = s.length();
    int dot = 0;
    for(int i=len-1;i>=0;--i){
        dot = ctoi(s[i])*n+dot;
        ans = string(1,itoc(dot%10))+ans;
        dot /= 10;
    }
    for(;dot;dot/=10){
        ans = string(1,itoc(dot%10))+ans;
    }
    return ans;
}

int main(){
    string ans;
    int N;
    while(cin>>N){
        ans = string(1,'1');
        for(int i=1;i<=N;++i){
            ans = multiply(ans,i);
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值