牛客网 10进制 VS 2进制(数学+进制转换) 附赠字符串加法,字符串与整数的乘法和除法模板

题目传送门

10进制 VS 2进制

题目描述

对于一个十进制数A,将A转换为二进制数,然后按位逆序排列,再转换为十进制数B,我们称B为A的二进制逆序数。 例如对于十进制数173,它的二进制形式为10101101,逆序排列得到10110101,其十进制数为181,181即为173的二进制逆序数。

输入描述:

一个1000位(即10^999)以内的十进制数。

输出描述:

输入的十进制数的二进制逆序数。

输入
173
输出
181

思路

进制转换+字符串运算模板题

粗略的估算了一下,开了个3400大小的string数组,提前算好2的n次幂,难点是字符串的运算。

2 3400 > 2 3330 = 2 10 333 ≈ 1 0 3 333 = 1 0 999 2^{3400}>2^{3330}={2^{10}}^{333} ≈ {10^{3}}^{333}=10^{999} 23400>23330=210333103333=10999

实现了字符串与常数的乘法和除法,实现了两个string类型字符串的加法。

代码

#include 
using namespace std;

string twopow[3400];
int remaind;
int munum;
int addnum;
//字符串除以一个常数
string devide(string s,int x){
    remaind=0;
    int len=s.size();
    for (int i=0;i<len;i++){
        int t=s[i]-'0'+remaind*10;
        s[i] = t/x+'0';
        remaind = t%x;
    }
    int pos=0;
    while (s[pos]=='0'){
        pos++;
    }
    s=s.substr(pos);
    if (s==""){
        s="0";
    }
    return s;
}
//字符串与一个常数的乘积
string mult(string s,int x){
    munum=0;
    reverse(s.begin(),s.end());
    int len=s.size();
    for (int i=0;i<len;i++){
        int t=s[i]-'0';
        s[i] = (t*x+munum)%10+'0';
        munum = (t*x+munum)/10;
    }
    while (munum!=0){
        s=s+(char)(munum%10+'0');
    	munum/=10;
    }
    reverse(s.begin(),s.end());
    return s;
}
//两个字符串相加
string add(string a,string b){
    int alen=a.size();int blen=b.size();
    if (alen<blen){
        swap(a,b);
        swap(alen,blen);
    }
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    addnum=0;
    for (int i=0;i<alen;i++){
        int an=a[i]-'0';
        int bn=0;
        if (i<blen){
            bn=b[i]-'0';
        }
        int ts = an+bn+addnum;
        a[i]=(char)(ts%10+'0');
        addnum=ts/10;
    }
    if (addnum){
        a=a+(char)(addnum+'0');
    }
    reverse(a.begin(),a.end());
    return a;
}

void init(){
    twopow[0]="1";
    for(int i=1;i<3400;i++){
        twopow[i]=mult(twopow[i-1],2);
    }
}
int main (){
    init();
    string a;
    while (cin>>a){
        string res="";
        while (a!="0"){
            a=devide(a,2);
            res=(char)(remaind+'0')+res;
        }
        int rlen=res.size();
        string ans="0";
        for (int i=0;i<rlen;i++){
            if (res[i]=='1'){
                ans=add(twopow[i],ans);
            }
        }
        cout<<ans<<endl;
    }

    return 0;
}

两个正整数字符串相加

/*********************************************************
  *Function:  add
  *Description: 两个字符串数字相加
  *Input:  需要外部定义一个进位标识addnum,传入参数为两个数字字符串
  *Return:  加和后的数字字符串
  *Others:  不考虑数字前的符号,不考虑浮点数
**********************************************************/
int addnum=0;
string add(string a,string b){
    int alen=a.size();int blen=b.size();
    if (alen<blen){
        swap(a,b);
        swap(alen,blen);
    }
    reverse(a.begin(),a.end());
    reverse(b.begin(),b.end());
    addnum=0;
    for (int i=0;i<alen;i++){
        int an=a[i]-'0';
        int bn=0;
        if (i<blen){
            bn=b[i]-'0';
        }
        int ts = an+bn+addnum;
        a[i]=(char)(ts%10+'0');
        addnum=ts/10;
    }
    if (addnum){
        a=a+(char)(addnum+'0');
    }
    reverse(a.begin(),a.end());
    return a;
}

正整数字符串乘一个正整数

/*********************************************************
  *Function:  mult
  *Description: 字符串和一个int型数字的乘积
  *Input:  需要外部定义一个进位标识munum,传入参数为string类型的数字字符串和int型整数
  *Return: 乘法运算后的数字字符串
  *Others:  不考虑负数的情况,不考虑浮点数字符串(正整数字符串乘一个正整数)
**********************************************************/
string mult(string s,int x){
    munum=0;
    reverse(s.begin(),s.end());
    int len=s.size();
    for (int i=0;i<len;i++){
        int t=s[i]-'0';
        s[i] = (t*x+munum)%10+'0';
        munum = (t*x+munum)/10;
    }
    while (munum!=0){
        s=s+(char)(munum%10+'0');
   		munum/=10;
    }
    reverse(s.begin(),s.end());
    return s;
}

正整数字符串除以一个正整数

/*********************************************************
  *Function:  devide
  *Description: 正整数字符串除以一个正整数
  *Input:  需要外部定义一个余数remaind,传入参数为string类型的数字字符串和int型整数
  *Return: 除法运算后的数字字符串
  *Others:  不考虑负数的情况,不考虑浮点数字符串(正整数字符串除以一个正整数)
**********************************************************/
string devide(string s,int x){
    remaind=0;
    int len=s.size();
    for (int i=0;i<len;i++){
        int t=s[i]-'0'+remaind*10;
        s[i] = t/x+'0';
        remaind = t%x;
    }
    int pos=0;
    while (s[pos]=='0'){
        pos++;
    }
    s=s.substr(pos);
    if (s==""){
        s="0";
    }
    return s;
}

你可能感兴趣的:(ACM训练)