poj1220(高精度模版,进制转换)

NUMBER BASE CONVERSION
Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 4050 Accepted: 1810

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

先普及一下高精度:

转自:http://blog.csdn.net/devillaw_zhc/article/details/7776578

一.高精度四则运算思想

高精度这个东西其实谁都会,上过小学数学课就知道高精度怎么做了,就是按照人的运算方式,一位一位运算。

1.加法 

就是 从个位开始 两个数字相加,如果有进位,就加到十位,再算十位相加,……

2.减法 

也是从个位开始 两个数字相减,如果得到的数字小于 0,那么就加上 10,并且把被减数的十位减一,……

3.乘法 

第一个数乘以第二个数的个位,写下来,右边与个位对齐,再与第二个数的十位相乘,右边与十位对齐,……

仔细想一想,会发现其实 第一个数 从右数起的第 i 位,不妨设为 2 乘以 第二个数从右数起的第 j 位,不妨设为 8,就相当于 2*10^(i-1) * 8*10^(j-1)

这个乘积所贡献的就是 答案从右数起的 第 i+j-1 位, 即 16 *10^(i+j-2) ,把 进位到 从右数起的第 i+j 位上,留下 6 . 即可。

4.除法 

除法其实是减法的延伸,打个比方,24723 除以 123 。

按照人的做法,从高位开始一位一位取出被除数的数字

先是 2,判断是否小于 123, 小于那答案这一位就置 0

再取一位,24, 还是小于,答案这一位置0

再取一位,247,这时候比 123 大了,那就看能减多少个 123, 发现减 次之后比 123 小了,那么答案的第 位上就是2, 减剩下的数是  

重复那个过程,取一位,12, 小于 123 ,答案这一位置 0

再取一位, 123, 不小于 123 了, 看能减多少个, 发现能减一个, 那么答案第 位就是 

剩下的数为 , 而被除数的数也被取光了,运算结束。

答案为 00201 ,整理一下即为 201


二、存储方式

实践下来为了方便起见,把最低位存在数组的第一位,最高位存在最后一位,是最容易编写程序的,道理很简单,因为每次都是从最低位开始做的,而且乘法显然会方便很多。

我一般用一个 struct 来表示一个高精度数,里面有个 数组, a[0] 为该数的长度,a[1] 是个位,a[2] 是十位,以此类推。


三.压位高精度

本质其实是一样的,只不过存储方式与输出方式有不同。

比如数 103 

用十位的高精度存 a[0] = 3, a[1] = 3, a[2] = 0, a[3] = 1

用百位的高精度存 a[0] = 2, a[1] = 3, a[2] = 1

要注意的是输出的时候 a[1] 不能只输出一个 3, 而要输出 03.


四.代码实现

#include <cstdio>
#include <cstring>
#include <algorithm>


using namespace std;


const int power = 1;      //每次运算的位数为10的power次方,在这里定义为了方便程序实现
const int base = 10;      //10的power次方。


//要压位的时候,只需改power 和 base即可,如压万位高精,那么power = 4, base = 10000


const int MAXL = 1001;    //数组的长度。


char a[MAXL], b[MAXL];
struct num
{
    int a[MAXL];
    num() { memset(a, 0, sizeof(a)); }                      //初始化
    num(char *s)                                            //将一个字符串初始化为高精度数
    {
        memset(a, 0, sizeof(a));
        int len = strlen(s);
        a[0] = (len+power-1) / power;                       //数的长度
        for (int i=0, t=0, w; i < len ;w *= 10, ++i)        
        {
            if (i % power == 0) { w = 1, ++t; }
            a[t] += w * (s[i]-'0');
        }
        //初始化数组,这里自己模拟一下,应该很容易懂的~
    }
    void add(int k) { if (k || a[0]) a[ ++a[0] ] = k; }     //在末尾添加一个数,除法的时候要用到
    void re() { reverse(a+1, a+a[0]+1); }                   //把数反过来,除法的时候要用到
    void print()                                            //打印此高精度数
    {
        printf("%d", a[ a[0] ]);      
        //先打印最高位,为了压位 或者 该高精度数为0 考虑
        for (int i = a[0]-1;i > 0;--i)
        printf("%0*d", power, a[i]);  
        //这里"%0*d", power的意思是,必须输出power位,不够则前面用0补足
        printf("\n");
    }
} p,q,ans;


bool operator < (const num &p, const num &q)              //判断小于关系,除法的时候有用
{
    if (p.a[0] < q.a[0]) return true;
    if (p.a[0] > q.a[0]) return false;
    for (int i = p.a[0];i > 0;--i)
    {
        if (p.a[i] != q.a[i]) return p.a[i] < q.a[i];
    }
    return false;
}


num operator + (const num &p, const num &q)               //加法,不用多说了吧,模拟一遍,很容易懂
{
    num c;
    c.a[0] = max(p.a[0], q.a[0]);
    for (int i = 1;i <= c.a[0];++i)
    {
        c.a[i] += p.a[i] + q.a[i];
        c.a[i+1] += c.a[i] / base;
        c.a[i] %= base;
    }
    if (c.a[ c.a[0]+1 ]) ++c.a[0];
    return c;
}


num operator - (const num &p, const num &q)               //减法,也不用多说,模拟一遍,很容易懂
{
    num c = p;
    for (int i = 1;i <= c.a[0];++i)
    {
        c.a[i] -= q.a[i];
        if (c.a[i] < 0) { c.a[i] += base; --c.a[i+1]; }
    }
    while (c.a[0] > 0 && !c.a[ c.a[0] ]) --c.a[0];          
    //我的习惯是如果该数为0,那么他的长度也是0,方便比较大小和在末尾添加数时的判断。
    return c;
}


num operator * (const num &p, const num &q)                 
//乘法,还是模拟一遍。。其实高精度就是模拟人工四则运算!
{
    num c;
    c.a[0] = p.a[0]+q.a[0]-1;
    for (int i = 1;i <= p.a[0];++i)
    for (int j = 1;j <= q.a[0];++j)
    {
        c.a[i+j-1] += p.a[i]*q.a[j];
        c.a[i+j] += c.a[i+j-1] / base;
        c.a[i+j-1] %= base;
    }
    if (c.a[ c.a[0]+1 ]) ++c.a[0];
    return c;
}


num operator / (const num &p, const num &q)               //除法,这里我稍微讲解一下
{
    num x, y;
    for (int i = p.a[0];i >= 1;--i)                       //从最高位开始取数
    {
        y.add(p.a[i]);             //把数添到末尾(最低位),这时候是高位在前,低位在后
        y.re();                    //把数反过来,变为统一的存储方式:低位在前,高位在后
        while ( !(y < q) )         //大于等于除数的时候,如果小于的话,其实答案上的该位就是初始的“0”
            y = y - q, ++x.a[i];   //看能减几个除数,减几次,答案上该位就加几次。
        y.re();                    //将数反过来,为下一次添数做准备
    }
    x.a[0] = p.a[0];
    while (x.a[0] > 0 && !x.a[x.a[0]]) --x.a[0];
    return x;
}


int main()
{
    scanf("%s", a);
    scanf("%s", b);
    reverse(a, a+strlen(a));
    reverse(b, b+strlen(b));

    p = num(a), q = num(b);

    ans = p + q;
    ans.print();

    ans = p - q;
    ans.print();

    ans = p * q;
    ans.print();

    ans = p / q;
    ans.print();
}


ac代码

#include <iostream>
#include <cstring>
using namespace std;
const int MAXN = 1005;
char str[MAXN];
int ans[MAXN],res[MAXN],start[MAXN];
int oldBase,newBase;

int getNum(char c){
    if(c>='0'&&c<='9') return c-'0';
    if(c>='A'&&c<='Z') return c-'A'+10;
    return c-'a'+36;
}
char getChar(int c){
    if(c>=0&&c<=9) return c+'0';
    if(c>=10&&c<=35)return c-10+'A';
    return c-36+'a';
}
void change(){
    start[0]=strlen(str);
    for(int i=1; i<=start[0]; i++)
        start[i]=getNum(str[i-1]);
}
void solve(){
    int i,j,y;
    memset(res,0,sizeof(res));
    while(start[0]>=1){
        i=1;y=0;
        ans[0]=start[0];
        while(start[0]>=i){
            y=y*oldBase+start[i];
            ans[i++]=y/newBase;
            y%=newBase;
        }
        res[++res[0]]=y;
        i=1;
        while(i<=ans[0]&&ans[i]==0) i++;
        memset(start,0,sizeof(ans));
        for(j=i; j<=ans[0]; j++) start[++start[0]]=ans[j];
        memset(ans,0,sizeof(ans));
    }
}
void print(){
    cout<<oldBase<<" "<<str<<endl<<newBase<<" ";
    for(int i=res[0]; i>=1; i--) cout<<getChar(res[i]);
    cout<<endl<<endl;
}
int main()
{
    int t;
    cin>>t;
    while(t--){
        cin>>oldBase>>newBase>>str;
        change();
        solve();
        print();
    }
    return 0;
}


某大牛写的,佩服

#include <stdio.h>
#include <string.h>
const int maxn = 1000;
int  t[maxn], A[maxn];
char str1[maxn], str2[maxn];
int n, m;
void solve()
{
    int i, len, k;
    len = strlen(str1);
    for(i=len; i>=0; --i) t[len-1-i] = str1[i] -(str1[i]<58 ? 48: str1[i]<97 ? 55: 61);
    for(k=0; len;) {
        for(i=len; i>=1; --i) {
            t[i-1] +=t[i]%m*n;
            t[i] /= m;
        }
        A[k++] = t[0] % m;
        t[0] /=m;
        while(len>0&&!t[len-1])  len--;
    }
    str2[k] =NULL;
    for(i=0; i<k; i++)
        str2[k-1-i] = A[i]+(A[i]<10 ? 48: A[i]<36 ? 55:61);
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d%s",&n, &m, str1);
        solve();
        printf("%d %s\n%d %s\n\n", n, str1, m, str2);
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值