PAT-1010 Radix (25)

题目大意:已知 A 的值和对应的 Xa 进制,在已知 B 值的情况下,问 B 值所对应的 Xb 进制(最小符合的进制)。

解题思路:本人花了 n 多个小时才 AC 了这道题,如果考场上估计只能拿21分(cai)。以下是我踩的坑。。。

坑一:A 转化为十进制数 v,以 A 的最大字母加1 (记做 minRadix) 作为进制下界之后随意选择了一个进制的上界(自认为pat测试数据水,就设了一个 100,改成10000???照样GG),采取顺序比较,结果有 4 个样例没有过;

    坑一之后感觉自己的进制上界设定地太随意了,于是准备找个上界(记做maxRadix)。思考过后,发现有两种情 况:

  1.    如果 B 只有一位,那么转化为十进制就是其本身 uu 没有所谓的上下界区别,最符合题意的就是 u+1
  2.    如果 B 是多位数,那么如果进制超过 v ,可想而知转化为十进制时必大于 v ,没有什么比较意义了。

    为了包含 1 的情况,2 做一些妥协(如果 1u == vv+1 就是最好选择),所以  v+1 作为上界是最好的选择了。

同时考虑到数据的刁钻性,顺序比较看来不行。直接推二分查找 (这很关键)。

坑二:改进后,分反而更低了。但明明进行了优化啊。问题一方面出在 u、v 的定义上,我设定的是 int 类型,显然大数情况下会溢出。于是改换了 long long。

坑三:依然没有解决那几组样例。原因是 long long 也会溢出,变为负数。可想而知出题者的测试数组会在long long范围里头,溢出的只会是些不满足题意的区间,于是改动了二分查找里面的一句判断,结果迎刃而解。(代码中有所标注)

题目链接:https://www.patest.cn/contests/pat-a-practise/1010

#include <iostream>    
#include <algorithm>    
#include <set>    
#include <map>    
#include <vector>    
#include <stack>    
#include <queue>    
#include <cmath> 
#include <cstring>   
using namespace std;

int toNum(char s)
{
	if(s>='0' && s<='9')
		return s - '0';
	else
		return s-'a'+10;
}

int getMinRadix(char s[])
{
	int minRadix = -1;
	for(int j=0;s[j]!='\0';++j)
		if(toNum(s[j]) > minRadix)
			minRadix = toNum(s[j]);
	return minRadix+1;
}

void cal(char s[],long long minRadix,long long maxRadix,long long v)
{
	long long i,j;
	while(minRadix <= maxRadix) 
	{
	//	cout << minRadix <<"," << maxRadix << endl; 
		long long u = 0;
		long long middleRadix = (minRadix+maxRadix)/2;
		for(j=0;s[j]!='\0';++j)
		{
			u = toNum(s[j]) + u*middleRadix; 
		}
		if(u == v)
		{
			cout << middleRadix << endl;
			return;
		}
		else if(u>v || u<0) //当long long溢出时,舍弃 middleRadix 以上那一部分 
		{
			maxRadix =  middleRadix-1;
		}
		else
		{
			minRadix =  middleRadix+1;
		}
	} 
	if(minRadix > maxRadix)
		cout <<  "Impossible" <<endl;
}
 
int main(int argc, char** argv) {
	long long tag,jz,n;
	char s1[15],s2[15],temp[15];
	cin >> s1 >> s2 >> tag >> jz;
	if(tag == 2)
	{
		strcpy(temp,s1);
		strcpy(s1,s2);
		strcpy(s2,temp);
	}
	
	long long v = 0;
	for(int i=0;s1[i]!='\0';++i)
	{
		v = toNum(s1[i]) + v*jz; 
	}
	
	int i,j;	
	long long minRadix = getMinRadix(s2);
	cal(s2,minRadix,v+1,v);	
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值