PAT (Advanced Level) Practice A1010 Radix (25 分)(C++)(甲级)(二分法)

版权声明:假装有个原创声明……虽然少许博文不属于完全原创,但也是自己辛辛苦苦总结的,转载请注明出处,感谢! https://blog.csdn.net/m0_37454852/article/details/86551105

1010基数(25分)
给定一对正整数,例如6和110,这个方程式6=110是真的吗?如果6是十进制数,110是二进制数,答案是“是”。
现在,对于任意一对正整数n1和n2,您的任务是找到一个数的基数,而另一个数的基数是给定的。
输入规格:
每个输入文件包含一个测试用例。每种情况都占用一行,该行包含4个正整数:
N1N2标签基数
其中,n1和n2各不超过10位。数字小于其基数,从集合0-9中选择,a-z其中0-9表示十进制数0-9,a-z表示十进制数10-35。如果标记为1,则最后一个基数是n1的基数;如果标记为2,则最后一个基数是n2的基数。
输出规格:
对于每个测试用例,在一行中打印另一个数字的基数,以便公式n1=n2为真。如果方程不可能,打印不可能。如果解不是唯一的,则输出尽可能小的基数。

Sample Input 1:

6 110 1 10
Sample Output 1:

2
Sample Input 2:

1 ab 1 2
Sample Output 2:

Impossible

///注意事项:一定要仔细考虑越界问题!!!

using namespace std;
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
typedef long long int LL;

char N1[20], N2[20];
int tag, radix, i, len1, len2;
long long int A = 0, B = 0;//N1, N2的十进制
double coe = 1;
int ch2num(char ch)//字符转化为数字
{
    if(ch >= '0' && ch <= '9') return ch - '0';
    return ch - 'a' + 10;
}

long long int N22B(long long int radix, int *flag)//把N2从radix进制转化为十进制
{
    long long int temp_B = 0;
    for(i=len2-1, coe = 1; i>=0; i--)//把N1转化为十进制
    {
        int x = ch2num(N2[i]);
        if(x >= radix) {*flag = 1; return -1;}//发现该进制过小,则返回一个无穷小量
        temp_B += x*coe;
        coe *= radix;
    }
    return temp_B;
}

int main()
{
    scanf("%s %s", N1, N2);
    scanf("%d %d", &tag, &radix);
    if(tag == 2)//保证N1为已知基数,N2为未知基数
    {
        char N3[20];
        strcpy(N3, N1);
        strcpy(N1, N2);
        strcpy(N2, N3);
    }
    len1 = strlen(N1);
    len2 = strlen(N2);
    for(i=len1-1, coe = 1; i>=0; i--)//把N1转化为十进制
    {
        A += ch2num(N1[i])*coe;
        coe *= radix;
    }
    LL l=2, r=(1LL<<63)-1, mid, smallest = 0;//r设置为longlong表示的最大数
    do
    {
        int flag = 0;
        mid = l+(r-l)/2;
        B = N22B(mid, &flag);//计算N2由mid进制转化成的十进制
        if(flag) l = mid+1;//说明该进制表示不了该数,需增大
        else if(A == B) smallest = mid, r = mid-1;//寻找最小基数
        else if( B > A || len2 > 1 && B < mid) r = mid-1;//注意可能为越界
        else if( B < A ) l = mid+1;
    }
    while(l<=r && !(mid == (1LL<<63)-1 && l<mid));//后面这个判断条件是防止l发生越界;但PAT测试用例中并没有这种情况
    if(smallest) printf("%lld", smallest);
    else printf("Impossible");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_37454852/article/details/86551105