PAT A1010 Radix

PAT A1010 Radix

在这里插入图片描述

Sample Input 1:

6 110 1 10

Sample Output 1:

2

Sample Input 2:

1 ab 1 2

Sample Output 2:

Impossible
word meaning
Radix 基数
while that of the other is given 当另一个已经给出时
  • 思路:将已知radix的n转化为十进制 [Q1] , 再找出[Q2]可以使另一个n转化为十进制以后相等的radix;

Q1:ToDecimal()的注意点:

case1:存储方式,已经数据范围:假设n1,radix1已知
radix1是题目给出的(一定合理,故<=35),n1最多有10位,所有转化为十进制数最大为:34 * (359 + 358 + … + 351 + 350 ) <= 3510 < 260 < 263,所有n1转化为十进制数是在long long的范围内的([-263 , 263-1])
为了避免类型强制转化出错,所有整型都用了long long
【注意:已经给出的进制一定<=35,因为多了没有字母哪来表示了,而另一个(要求radix的)的进制可能超过35】


Q2: 求另一个(假设为n2)的radix:
这是一个查找问题:
首先想到的是暴力法 从2开始枚举:会有2组数据出错(样例0、样例7:得分23/25,其实…就差不多了)

进一步优化,可以发现有序性:radix越大,转换为十进制数越大,因为转换为十进制是累加每一位i*radixi-1,故可以采用二分法来查找n2的radix,这里又引出了问题:Q2-1:二分的上下界
Q2-1:
下界lower很好确定:一定是n2中最大的位 + 1,如 10a3bf812 中 f最大,radix最小应为f+1即(16进制)
上界upper的确定:开始的时候我以为也是不超过35,结果Wrong,后来想到:比如n1 = 1000000000; n2 = 10;,n1的进制已知为35 , 则若n1==n2,n2的进制应取: 359

当n2取最小时(即10,至少有2位,只有一位最大35,radix就不会超),n2转化为十进制为 1 * radix2 1。换句话说,n2 转化为十进制一定比他的基radix2大,
即ToDecimal(n2) > radix2,即ToDecimal(n1) > radix2;(ToDecimal(n1) == ToDecimal(n2)),上界最大为: ToDecimal(n1)+1;

还有一个特殊情况就是,如果n1转化为十进制以后的数ToDecimal(n1)比lower还小,比如n2 = 10a3bf812; ToDecimal(n1) = 5; 如果upper还取 ToDecimal(n1)+1,上界比下界lower还小了!这时应取上界为lower+1;

case1:要求n2 转化为10进制可能会超过long long 范围,因为radix2可能超过35,所有需要判断是否溢出,若溢出(< 0)应按INF算

…好乱啊啊啊啊啊啊!…

  • code :
#include <bits/stdc++.h>
#include <string>
using namespace std;
typedef long long ll;
ll INF = (1ll << 63) - 1; 

ll GetDigit(char c){
	if(islower(c)) return c - 'a' + 10;
	else return c - '0';
}
ll ToDecimal(string s, int r){
	ll ans = 0;
	for(int i = 0; i < s.size(); ++i){
		ll dig = GetDigit(s[i]);
		ans = ans * r + dig;
	}
	return ans;
}
ll BinSearch(ll left, ll right, string s, ll x){
	while(left <= right){
		ll mid = (left + right) / 2;
		ll tmp = ToDecimal(s, mid);
		if(tmp == x){
			return mid;
		}else if(tmp < 0){	//Wrong 1: 样例0, 样例7,待查询n转换为10进制时溢出 
			right = mid - 1;
		}else if(tmp > x){
			right = mid - 1;
		}else{
			left = mid + 1;
		}
	}
	return -1;
}
ll GetMaxDigit(string s){
	ll Max = 0;
	for(int i = 0; i < s.size(); ++i){
		Max = max(Max, GetDigit(s[i]));
	}
	return Max;
}
int main(){
	vector<string> s(3);
	ll tag, radix;
	cin >> s[1] >> s[2];
	scanf("%lld %lld", &tag, &radix); 
//	if(s[1] == s[2]) printf("%lld", radix);	//判特:样例 10: 可以剪一枝 
	ll cmp = ToDecimal(s[tag], radix);	// other = s[3-tag]
	ll lower = GetMaxDigit(s[3-tag]) + 1;
	ll upper = max(lower, cmp) + 1;
	ll ans = BinSearch(lower, upper, s[3-tag], cmp);
	if(ans != -1) printf("%lld", ans);
	else printf("Impossible");
	return 0;
}
发布了271 篇原创文章 · 获赞 5 · 访问量 6535

猜你喜欢

转载自blog.csdn.net/qq_42347617/article/details/99730099