甲级-1010 Radix (25 分)

题目:

Given a pair of positive integers, for example, 6 and 110, can this equation 6 = 110 be true? The answer is yes, if 6 is a decimal number and 110 is a binary number.

Now for any pair of positive integers N1 and N2, your task is to find the radix of one number while that of the other is given.

Input Specification:

Each input file contains one test case. Each case occupies a line which contains 4 positive integers:

N1 N2 tag radix

Here N1 and N2 each has no more than 10 digits. A digit is less than its radix and is chosen from the set { 0-9, a-z } where 0-9 represent the decimal numbers 0-9, and a-z represent the decimal numbers 10-35. The last number radix is the radix of N1 if tag is 1, or of N2 if tag is 2.

Output Specification:

For each test case, print in one line the radix of the other number so that the equation N1 = N2 is true. If the equation is impossible, print Impossible. If the solution is not unique, output the smallest possible radix.

Sample Input 1:

6 110 1 10

Sample Output 1:

2

Sample Input 2:

1 ab 1 2

Sample Output 2:

Impossible

解题思路:

题目本身并不是很难,假设给出了N1的进制,可以先将N1转化为十进制,然后从(radix=2)开始以某种方式试探N2的进制,最后使得N2在转换为十进制后与N1相等即可。只是这上面的坑有点多。

坑点:

1.需要注意,测试用例中给出的radix不一定小于等于36,而且本题中出现的数据都远超过int能保存的范围,到目前为止个人觉得最好的办法还是自己构建一个类来保存数据。笔者是使用deque来保存数据的,但毕竟不是自己单独定义的类,导致编码看起来很混乱。
之后查看其他人的解题思路发现用long long就可以……所以大概是我多虑了)
2.除了数据过大之外,在查找目标radix的过程中需要运用适当的方法,不然会超时。看网络上其他人的方法多为使用二分查找,在这里我感觉再对deque定义除法运算太耗时了,便取巧定义了一个变量做“步长”——
第一次以1111111111为步长搜索,
第二次以111111111为步长搜索,
……
最后一次以1为步长搜索,
在步长为1时搜索必然能命中结果,若不命中,则说明不存在,打印Impossible。使用此方法,最后也不会超时。
3.需要考虑到的特殊情况:进制数应大于原数中的每一位;当答案不唯一时,输出最小的进制数。即——
当test case为10 50 1 10时应输出Impossible,而非2;
当test case为3 3 1 10时应输出4,而不是其他数字。

代码:

编译器:C++(g++)

#include 
#include 
#include 
using namespace std;

//数字转换为deque的形式
deque atodeq(long long n)
{
    deque ret;
    while(n!=0)
    {
        ret.push_front(n%10);
        n/=10;
    }
    return ret;
}
//两个deque形式的数字相加
deque sum(deque s1,deque s2)
{
    if(s1.size() ret;
    while(!s2.empty())
    {
        ret.push_front((s1.back()+s2.back()+jinwei)%10);
        jinwei=(s1.back()+s2.back()+jinwei)/10;
        s1.pop_back();
        s2.pop_back();
    }
    while(!s1.empty())
    {
        ret.push_front((s1.back()+jinwei)%10);
        jinwei=(s1.back()+jinwei)/10;
        s1.pop_back();
    }
    if(jinwei!=0)
    {
        ret.push_front(jinwei);
    }
    return ret;
}
//两个deque形式的数字相乘
deque times(deque s1,deque s2)
{
    int i=0;
    deque ret(1,0);
    while(!s2.empty())
    {
        deque tmp=s1;
        int jinwei=0;
        for(int j=tmp.size()-1;j>=0;--j)
        {
            int t=tmp[j];
            tmp[j]=(t*s2.back()+jinwei)%10;
            jinwei=(t*s2.back()+jinwei)/10;
        }
        if(jinwei!=0)
        {
            tmp.push_front(jinwei);
        }
        for(int j=0;j!=i;++j)
        {
            tmp.push_back(0);
        }
        ++i;
        ret=sum(ret,tmp);
        s2.pop_back();
    }
    return ret;
}
//将str形式的radix进制的数字转换为10进制的deque的形式
deque toDecimal(const string &str,long long radix)
{
    deque ret(1,0);
    string num=str;
    for(deque i(1,1);!num.empty();i=times(i,atodeq(radix)))
    {
        int t;
        if(num.back()>='0'&&num.back()<='9')
        {
            t=num.back()-'0';
        }
        else
        {
            t=num.back()-'a'+10;
        }
        ret=sum(ret,times(atodeq(t),i));
        num.pop_back();
    }
    return ret;
}
deque toDecimal(const string &str,deque radix)
{
    deque ret(1,0);
    string num=str;
    for(deque i(1,1);!num.empty();i=times(i,radix))
    {
        int t;
        if(num.back()>='0'&&num.back()<='9')
        {
            t=num.back()-'0';
        }
        else
        {
            t=num.back()-'a'+10;
        }
        ret=sum(ret,times(atodeq(t),i));
        num.pop_back();
    }
    return ret;
}

int main()
{
    string n1,n2;
    int tag;
    long long radix;
    cin>>n1>>n2>>tag>>radix;
    //特殊情况:两者都是个位数
    if(1==n1.size()&&1==n2.size())
    {
        if(n1==n2)
        {
            if(n1.back()>='0'&&n1.back()<='9')
            {
                cout<<(n1.back()-'0'+1)< num;
    if(2==tag)
    {
        swap(n1,n2);
    }
    num=toDecimal(n1,radix);
    //考虑最小进制数应大于每一位数的情况
    int minRet=2;
    for(auto it=n2.cbegin();it!=n2.cend();++it)
    {
        if(*it>='0'&&*it<='9')
        {
            minRet=((*it-'0'+1)>minRet?(*it-'0'+1):minRet);
        }
        else
        {
            minRet=((*it-'a'+11)>minRet?(*it-'a'+11):minRet);
        }
    }
    if(n1.size()max)
            {
                //min>max说明没有合适的进制
                cout<<"Impossible"<num.size()||(result.size()==num.size()&&result>num))
            {
                //大于则向前半区查找
                max=ret-1;
                ret=(min+max)/2;
            }
            else
            {
                //等于则输出
                cout<radix
        deque ret=atodeq((radix>minRet?radix:minRet)),pre=ret;
        //考虑n2为个位数的情况
        if(1==n2.size())
        {
            if(toDecimal(n2,ret)!=num)
            {
                cout<<"Impossible"<num.size()||(result.size()==num.size()&&result>num))
            {
                //步长为1的时候必然会命中,否则就是Impossible
                if(increase!=1)
                {
                    --increase;
                    ret=pre;
                }
                else
                {
                    cout<<"Impossible"<(increase,1));
        }
    }
    return 0;
}

你可能感兴趣的:(甲级-1010 Radix (25 分))