PAT甲级 1010 Radix(二分)

前言

一道二分的好题。

题目概述

1010 Radix

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

AC代码

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

using LL = long long;

LL trans(string s, int radix)
{
	LL p[15];
	LL cnt = 0;

	int k = 0;
	p[k] = 1;
	for (int i = s.size() - 1; i >= 0; --i)
	{
		LL c = isdigit(s[i]) ? s[i] - 48 : s[i] - 'a' + 10;
		cnt += c * p[k];
		p[k + 1] = p[k] * radix;
		++k;
	}

	return cnt;
}

LL find(string n, long long num) {
	char it = *max_element(n.begin(), n.end());
	long long low = (isdigit(it) ? it - '0' : it - 'a' + 10) + 1;
	long long high = max(num, low);
	while (low <= high) {
		long long mid = (low + high) / 2;
		long long t = trans(n, mid);
		if (t < 0 || t > num) high = mid - 1;
		else if (t == num) return mid;
		else low = mid + 1;
	}
	return -1;
}

int main()
{
	string s1, s2;
	int tag, radix;
	cin >> s1 >> s2 >> tag >> radix;
	if (tag == 2) swap(s1, s2);

	LL t = find(s2, trans(s1, radix));
	if (t == -1) cout << "Impossible" << endl;
	else cout << t << endl;
	return 0;
}

分析思路

1.首先把题目给定进制的那个数字转化为十进制下的大小,这个地方估算可得,因为最大是36进制,所以long long类型存的下,不需要开高精度。

2.对于要判断进制的数字,情况分析如下,首先,它的答案如果存在,则其进制一定在该数字最大出现的数字 + 1 ~ 该数字大小 这个区间之内。

3.继续注意到,进制具有单调性,对于同样的一个数字串,进制越大则其转化为十进制数字的大小也会越大,这符合二分单调性的性质。

4.利用二分查找进制答案,注意这个地方是有可能会爆掉long long的,所以要加一个判断是否为负数,如果是负数就代表已经溢出,那么他肯定是二分中偏大的答案,也要把二分区间的右边界向左半部分调整。

文末广告

学习算法和数据结构真的是个很累的过程,不会做只能求助于题解。 因为写代码这个东西基本上是千人千面。同时网络上搜到的题解很多要么用到的是自己还没学到的知识,看不懂;要么内核过于简陋,只能糊弄当前题目,不具有普适性。
如果你是一个喜欢做洛谷,ACwing和PTA的题目的同学,欢迎关注我的博客,我主要在这三个平台上做题,认为有价值和有难度的题目我会写题解发布出来。

TreeTraverler的往期文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

102101141高孙炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值