题目链接
题目描述与示例
给定一个十进制数M,以及需要转换的进制数N。将十进制数M转化为N进制数
输入描述
输入为一行,M(32位整数)、N(2 ≤ N ≤ 16),以空格隔开。
输出描述
为每个测试实例输出转换后的数,每个输出占一行。如果N大于9,则对应的数字规则参考16进制(比如,10用A表示,等等)
示例
输入:
7 2
输出:
111
解题思路
题目分析
这个题目还是比较容易理解的,就是把十进制数字M转化为N进制,超过10的部分按十六进制格式输出
个人思路
- 先写普遍情况即N<9时,因为这个时候全是数字
- 辗转相除获取余数存放到vector里面
- 逆置vector输出即可
- 对大于10的数字一一替换成ABCDE
为了避免有些小伙伴不知道辗转相除具体是怎么实现的,这里我直接从网上抠了个图过来描述一下我的理解:
29转化为2进制,按上述我的思路计算完了之后vector存放的数据为10111,所以需要逆置成11101才是正确的输出形式,有关辗转相除的进制转化原理,在查看了各路大神的解释后我的理解大致如下:
(本来我以为我可以直接描述的,好像不太会措辞了,所以还是结合实例吧,这里还是29转2进制)
- 29%2=1
- [(29-1*2^0)%2]%2=0
- {[(29 - 1* 2^0) % 2 - 0*2^1] % 2 }%2= 1
- …………
大致思路其实就是除以进制,得到低位,然后减去低位,继续除以进制得到高位,只不过运算更为方便简洁,每一步余数都是计算得出的数位上的数字,还省下了减去低位的运算过程,不得不说发明这个算法的人的确很厉害。比如上述的第一步求出的就是29对应二进制位的第一位数字,以此类推。
代码展示
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
int M,N;
cin>>M>>N;
vector<string> A;
while(M%N !=M )
{
int b=M%N;//余
if(b==10)
A.push_back("A");
else if(b==11)
A.push_back("B");
else if(b==12)
A.push_back("C");
else if(b==13)
A.push_back("D");
else if(b==14)
A.push_back("E");
else if(b==15)
A.push_back("F");
else
A.push_back(to_string(b));
M=M/N;
}
//完了对M还需要判断
if(M==10)
A.push_back("A");
else if(M==11)
A.push_back("B");
else if(M==12)
A.push_back("C");
else if(M==13)
A.push_back("D");
else if(M==14)
A.push_back("E");
else if(M==15)
A.push_back("F");
else
A.push_back(to_string(M));
reverse(A.begin(),A.end());
for(auto e:A)
{
cout<<e;
}
return 0;
}
但是很可惜上述代码跑不过,会有部分测试用例跑不过,因为我在做的时候看不到他的测试用例只知道跑不过所以当时也没有发现问题所在,知道看题解的时候才知道是自己忽略的M可能是一个负数的情况。
当M是一个负数的话那么vector里面的数字都是负数,这样输出出来的数据是不符合规则的,所以给出了下列解决方案:
- 定义一个bool类型的flag=false
- 如果M为负数,就让M=-M,flag=true
- 在最后输出vector时判断
- 如果flag=true就输出一个’-'号即可
具体解决方案已经给出,代码的话感兴趣的可以自己添上(不过大概率没人会像我这么做)
题解
关于题解大致思路都是一样的,只是部分细节处理上稍有不同,这里就直接给出我觉得最简洁的,先上代码:
#include <iostream>
using namespace std;
int main(){
string s="",table="0123456789ABCDEF";
int m,n;
cin>>m>>n;
while(m){
if(m<0){
m=-m;
cout<<"-";
}
s=table[m%n]+s;
m/=n;
}
cout<<s<<endl;
return 0;
}
这个原理实际上也是辗转相除的思想,就不多说,这个精髓就在于有一个table的串把0-15的数字以及对应字母都保存了下来,取出余数后可以直接通过下标访问到table串里对应的元素,就不需要我那样傻傻的转化成字母;再者我觉得比较新颖的地方在于在拼接字符串的时候他用的是s=table[m%n]+s,而不是s+=table[m%n],一般对我来讲,因为用习惯了后面的那种拼接方式然后逆置整个串,就忽略了这样的拼接,这样的拼接就直接少了一次对字符串的逆置。