版权声明:本文为博主原创,未经博主允许不得转载。转载请附上原文链接。 https://blog.csdn.net/qq_38341682/article/details/88606591
题目描述
对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们乘B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。
输入描述
一个1000位(即10^999)以内的十进制数。
输出描述
输入的十进制数的二进制逆序数。
分析
这道题也是一道大数运算的题目,不过这道题稍微复杂一点,因为不仅考察了大数除法,也考察了大数乘法。对于大数运算,可以使用string来存储大数,也可以使用数组来存储大数。博主之前的文章介绍了使用数组来存储大数进行运算的操作,这道题就选用string来存储进行运算。比较这两种方式后,我觉得还是使用数组比较方便一点,毕竟不用在字符和数字之间进行转换。
这道题需要注意一点的是,不能在将10进制转化为2进制后,再将2进制转化为10进制,这样会超时,这两个步骤应该同时进行。即在计算出2进制的一位数之后,就开始将其转化为10进制数,和快速幂运算有相似的思想。大数除法和大数乘法都使用博主之前文章中介绍的方法,整个转化过程结束的条件是原始输入为0,可以单独写一个函数来判断string是否为0。最后输出时一定注意要反序输出string,因为每次进位都直接加在string的最后,也就是说string的最后一个字符是最高位,所以要反序输出。
AC代码如下:
#include<iostream>
#include<string>
using namespace std;
bool is0(string str)//判断string是否为0
{
int length = str.length();
for(int i = 0; i < length; ++i)//需要每一位都为0
{
if(str[i] != '0')
{
return false;
}
}
return true;
}
int main(void)
{
string str;
while(cin >> str)
{
int length = str.length();
string result = "";//结果
while(!is0(str))//string不为0
{
int temp = 0, tmp = 0;//temp两个过程都会使用,是连接两个过程桥梁
for(int i = 0; i < length; ++i)//大数除法
{
temp = temp*10 + (str[i]-'0');//商为0时的借位
str[i] = temp / 2 + '0';//商
temp %= 2;//余数
}
int len = result.length();
for(int i = 0; i < len; ++i)//大数乘法
{
//temp为上一阶段2进制数中的一位数
//因为只是一位数,所以可以先加上,再算其他数位乘以2的值
tmp = (result[i]-'0')*2 + temp;
result[i] = tmp % 10 + '0';
temp = tmp / 10;//进位
}
if(temp != 0)//最高位的进位
{
result += (temp + '0');//最高位在尾部
}
}
for(int i = result.length()-1; i >= 0; --i)//反序输出,最高位在最后
{
cout << result[i];
}
}
return 0;
}