1010 Radix (25 分),PTA

题目:https://pintia.cn/problem-sets/994805342720868352/problems/994805507225665536

题意:给定n1、n2两个数,求可以是两者相等的进制;如果没有,输出Impossible

思路:

①暴力枚举进制数,超时/wa,错在样例7,这样写最多只能有24分。

盲猜样例7应该是这样的

input: 
9999999999 9999999999 1 10
output:
10

②开二分搜索进制数,转换出来的数会爆long long,所以二分的check要修改一下。

当要求的数只有一位时,不管是多少进制的数,算出来的答案都是一样的,so特判一下。

当要求的数大于一位时,答案如果存在,则唯一。

盲猜样例一应该是这样的

input: 
11 9 1 8
output:
10 

 

tips:

①巧妙利用swap函数减少函数长度

②for()中不要用i<s.szie()或者i<strlen(s),O(n)会变成O(n*n)

 

附上代码:

#include<bits/stdc++.h>
using namespace std;
const long long inf=(1ll<<31)-1;
long long cal(string s,long long radix)//计算s的radix进制数,转换成10进制数的值 
{
    long long ans=0,rdixnum=1;
    int len=s.size();
    for(int i=len-1;i>=0;i--)
    {
        if(s[i]>='0'&&s[i]<='9')ans+=1ll*(s[i]-'0')*rdixnum;
        else ans+=1ll*(s[i]-'a'+10)*rdixnum;
        rdixnum*=radix;
    }
    return ans;
}

int main()
{
    string s1,s2;
    int tag,len1,len2;
    long long ansnum=0,radixnum=1,ans=-1,radix;
    cin>>s1>>s2>>tag>>radix;
    
    if(tag==2)swap(s1,s2);//交换 
    len1=s1.size();
    len2=s2.size();
    
    for(int i=len1-1;i>=0;i--)
    {
        if(s1[i]>='0'&&s1[i]<='9')ansnum+=1ll*(s1[i]-'0')*radixnum;//计算已给数的十进制数值 
        else ansnum+=1ll*(s1[i]-'a'+10)*radixnum;
        radixnum*=radix;
    }
    long long l=1,r=inf;
    for(int i=0;i<len2;i++)
    {
        if(s2[i]>='0'&&s2[i]<='9')l=max(l,s2[i]-'0'+1ll);//计算满足字母、数字要求的最小进制 
        else  l=max(l,s2[i]-'a'+11ll);
    }
    if(len2==1) 
    {
        if(ansnum==cal(s2,l))cout<<l<<endl;
        else cout<<"Impossible"<<endl;
    }
    else
    {
        while(l<=r)
        {
            long long mid=l+r>>1ll;
            if(cal(s2,mid)==ansnum)
            {
                cout<<mid<<endl;
                return 0;
            }
            else if(cal(s2,mid)>ansnum||cal(s2,mid)<0)r=mid-1;//修改二分 
            else l=mid+1;
        }
        cout<<"Impossible"<<endl;
    }
    return 0; 
}

 

我还是太难♂了

/(ㄒoㄒ)/~~

posted @ 2019-11-25 16:18  myrtle  阅读(165)  评论(0编辑  收藏  举报