POJ 1220关于大数的进制转换

问题描述:

已知:位数为K(0 < K <200)的N进制数P(2 ≤ N ≤62),该数由0-9, A-Z, a-z组成,其中A-Z代表10-35,a-z代表36-61

求:转换为M进制(2 ≤ M ≤62)后的新数Q


输入:第1行为case数T;第2至第T+1行为T个case,每行输入均为N、M以及P,用空格分隔

输出:采用以下形式输出

N P

M Q

空行

……


Sample Input:

1

62 2 abcdefghiz


Sample Output:

62 abcdefghiz

2 11011100000100010111110010010110011111001001100011010010001


在1220的讨论区中,盛传着一位大神的精简代码,其核心部分就是:

for(l=0;k;){
			for(i=k;1<i--;){
				t[i-1]+=t[i]%b*a;
				t[i]/=b;
			}
			A[l++]=t[0]%b;
			t[0]/=b;
			for(;0<k&&!t[k-1];k--);
		}
要看懂这段代码,还是必须从最基本的算法推导开始。我们最熟悉的是十进制转化为其他进制的过程,如将29转化成2进制数的过程:

                                商            余数

(1)     29/2              14              1

(2)     14/2                7              0

(3)       7/2                3              1

(4)       3/2                1              1

(5)       1/2                0              1

   29的二进制为:11101,注意是余数的倒序。

我们将其推广到更普通的情形,网上用的一个例子是将二进制转化为八进制:1010011——123,将二进制转为八进制,还是使用相除取余的方法,这一次除数为8。

                                           商                         余数

第一轮:   (0*2+1)/8            0                             1

                 (1*2+0)/8            00                            2

                 (2*2+1)/8            000                          5

                 (5*2+0)/8            0001                        2

                 (2*2+0)/8            00010                      4

                 (4*2+1)/8            000101                    1

                 (1*2+1)/8            0001010                  3

     第一轮的过程如此麻烦,它的整个过程实际上是将1010011除以8,将8转化为2进制(1000)在纸上进行推算整个过程会更清晰一些,等到的商为1010,余数为3,得到的余数3即是八进制的最后一位上的数。


第二轮:继续对上一轮所取得的商1010进行除8:

                                            商                          余数

             (0*2+1)/8                 0                             1

             (1*2+0)/8                 0                             2

             (2*2+1)/8                 0                             5

             (5*2+0)/8                 1                             2

     同样最后所得的余数2为对应八进制数的倒数第二位。


第三轮:对1除8,所得余数为1,对应八进制的第一位为1,而所得的商为0,结束,于是对应的八进制为123。

     根据对更普遍的情况的整个过程有了初步的了解,可以进行代码的编写了。

#include <stdio.h>
#include <string.h>

int search(char c);

char num[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

int main()
{
	int i,j,k,a,b,count,length,lt;
	char A[256],B[256];
	int buffer[256],s[256];

	scanf("%d",&count);
	for(i=0;i<count;i++)
	{
		scanf("%d %d %s",&a,&b,A);

		length=strlen(A);

		for(j=1;j<=length;j++)
			s[j]=search(A[j-1]);
		s[0]=0;

		k=1;
		lt=0;
		while(1)
		{
			for(;k<=length;k++)
			{
				s[k]+=(s[k-1]%b)*a;
				s[k-1]/=b;
			}
			buffer[lt++]=s[k-1]%b; //得到的B是倒序的
			s[k-1]/=b;

			k=0;
			while(s[k]==0 && k<=length)
				k++;
			if(k==length+1)
				break;
		}

		for(k=0;k<lt;k++)
		{
			B[k]=num[buffer[lt-1-k]];
		}
		B[k]='\0';

		printf("%d %s\n",a,A);
		printf("%d %s\n",b,B);
		printf("\n");
	}

	return 0;
}

int search(char c)
{
	int l=0,r=61;
	int m;

	while(l<=r)
	{
		m=(l+r)*0.5;

		if(c<num[m])
			r=m-1;
		else if(c==num[m])
			return m;
		else if(c>num[m])
			l=m+1;
	}
	return -1;
}
需要注意的是,这段代码得到的b进制数是逆序的,需要进行处理才能输出正确的b进制数。

    





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值