题目编号 :Exp06-Enhance05,freshman-1022
题目名称:十进制转换任意进制
题目描述:编写程序,用递归方法将十进制的非负整数 N 转换为 b 进制数(2≤b≤36),其中字符、ASCII码值和数值之间的对应关系如下:
输入:一行输入两个非负整数,分别是十进制的 N 和 b ,其中 0 <=N <=2^31 ,2 <=b <= 36 。
输出:N 的 b 进制数。
样例1:
输入:
579 8
输出:
1103
样例2:
输入:
579 20
输出:
18J
方法一:循环
#include <stdio.h>
#include <math.h>
int main()
{
long long N,b;
scanf("%lld%lld",&N,&b);
long long M=N;
long long a[99]={0},i=0,j,k,q,cnt=0;
do{
N/=b;
cnt++;
}while(N>0);
long long sum=cnt-1;
while(M>0){
q=i+1;
a[q-1]=M/(long long)pow((double)b,(double)sum);
M=M-(long long)pow((double)b,(double)sum)*a[q-1];
sum--;
i+=1;
}
for(j=0;j<=cnt-1;j++){
if(a[j]>=0&&a[j]<=9)printf("%c",a[j]+48);
else if(a[j]>=10&&a[j]<=35)printf("%c",a[j]+55);
}
return 0;
}
注意:
1.pow函数的函数原型为double pow(double x,double y);有时在自己的IDE上可以运行通过但oj系统会判错,所以常常需要用到强制类型转换。
2.在定义一开始时的a[]时需要初始化为{0}。若不初始化,假使输入81408 8,则会输出 237(正确的应该是237000)。这是因为while循环的结束条件为M>0.因此到M=0后就退出循环了,原本转换的进制之后有0也无法输出。
3.在printf的for循环中,结束条件是cnt-1而不是i。如果结束条件为j<i的话,则与上述注意点2所讲述的一样,只能输出数组a中不为0的数。
方法二:递归
#include <stdio.h>
typedef long long ll;
void f(ll x, ll n) {
if (x == 0)return;
else {
f(x / n, n);
if (x % n < 10)printf("%c",x%n+'0');
else printf("%c",x % n - 10 + 'A');
}
}
int main() {
ll x, n;
scanf("%lld%lld", &x, &n);
if (x == 0)printf("%lld", x);
f(x, n);
return 0;
}
方法二关键在于理解逐层递归的退出。当多层递归一直递归到x/n=0的时候,上面if语句的return 只不过是退出了当前的递归。
另外,本题的一大亮点在于将比较复杂的long long 采用typedef转化成了简单易写的ll,这种手法值得学习。