PAT 甲级 1010 Radix (25 分) (二分+模拟 )

题意:给两个不超过10位的数和其中一个数的进制,求使得两个数相等的最小的另一个数的进制,若不存在,输出Impossible。

思路:题目说输入的数最大为35,我理所当然认为最大进制就是36,进行了枚举。结果过不了,,好吧,事实上输出的进制多大都有可能,只要使得两数相等,那么枚举肯定不行了,需使用二分,那么上限为多少呢,尽可能大就好了,我做的时候直接将上限设为了1e18,因为进制数必须比给出的数字中的任何一个都大,所以下限为基数中最大数+1。

注意:输入的数可能很大,需要用long long,计算进制的时候可能会溢出long long,变为负数,解决方案是,要么特判<0的情况(<0即为溢出),要么直接用unsigned long long进行计算。

代码:

#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define inf 0x3f3f3f3f
typedef unsigned long long ll;
const ll maxx = 1e18;
int get_num(char s)  //char-int转换
{
    if(s>='a'&&s<='z')
        return s-'a'+10;
    else
        return s-'0';
}
ll f(string s,ll base) //string-int转换
{
    ll ans=0;
    for(int i=0;i<s.size();i++)
        ans=ans*base+get_num(s[i]);
    return ans;
}
void solve(ll x,string s)
{
    int maxt=0;
    for(int i=0;i<s.size();i++)
        maxt=max(maxt,get_num(s[i]));
    ll l=maxt+1,r=maxx,mid;
    while(l<r)  //整数二分
    {
         mid=l+r>>1;
         if(f(s,mid)>=x)
            r=mid;
         else
            l=mid+1;
    }
    if(f(s,l)!=x)
        cout<<"Impossible"<<endl;
    else
        cout<<l<<endl;
}
int main()
{
    string s1,s2;
    int flag,base;
    cin>>s1>>s2>>flag>>base;
    ll a,b;
    if(flag==1) 
    {
        a=f(s1,base);
        solve(a,s2);
    }
    else
    {
        b=f(s2,base);
        solve(b,s1);
    }
    return 0;
}


你可能感兴趣的:(PAT甲级,二分)