PAT_1010. Radix
来源:互联网 发布:mac新系统不能用word 编辑:程序博客网 时间:2024/06/08 17:18
//// main.cpp// PAT_1010. Radix//// Created by wjq on 17/3/30.// Copyright © 2017年 wjq. All rights reserved.//// N1 N2 tag radix#include <iostream>#include <string.h>#define MIN(a,b) (a)<(b)?(a):(b)using namespacestd;int tag;char N1[15],N2[15],sourceN[15],targetN[15];long longint radix,sourceNum,low,high,mid;long longint CharToDecimal(char N[],longlong int jinzhi){ longlong int sum=0,n=1; for(int i=(int)strlen(N)-1;i>=0;i--) { if(isdigit(N[i])) sum+=(N[i]-'0')*n; elseif(isalpha(N[i])) sum+=(N[i]-'a'+10)*n; n*=jinzhi; if(sum<0) return -1; } return sum;}long longint BinarySearch(){ low=2; for(int j=0;j<strlen(targetN);j++) { longlong int temp=0; if(isdigit(targetN[j])) temp=targetN[j]-'0'; else temp=targetN[j]-'a'+10; if(temp>low) low=temp+1; } high=sourceNum+1; while(low<=high) { mid=(low+high)/2; if(CharToDecimal(targetN,mid)==sourceNum) returnmid; elseif(CharToDecimal(targetN,mid)<sourceNum&&CharToDecimal(targetN,mid)!=-1) low=mid+1; else high=mid-1; } return -1;}void Sure(){ if(tag==1) { strcpy(sourceN,N1); strcpy(targetN,N2); sourceNum=CharToDecimal(N1,radix); } else { strcpy(sourceN,N2); strcpy(targetN,N1); sourceNum=CharToDecimal(N2,radix); } }int main(int argc,const char * argv[]){ cin>>N1>>N2>>tag>>radix; if(strcmp(N1,"1")==0&&strcmp(N2,"1")==0) cout<<2; elseif(strcmp(N1,N2)==0) { if(strlen(N1)==1) { if(tag==1) { if(isalpha(N1[0])) cout<<(MIN(radix,N2[0]-'a'+11)); elsecout<<(MIN(radix,N2[0]-'0'+1)); } else { if(isalpha(N1[0])) cout<<(MIN(radix,N2[0]-'a'+11)); elsecout<<(MIN(radix,N2[0]-'0'+1)); } } elsecout<<radix; } else { Sure(); if(BinarySearch()==-1) cout<<"Impossible"; else cout<<BinarySearch(); }}
思路:
根据tag确定源字符和目标字符,通过源进制算出源数,再通过枚举目标进制算出目标数,若目标数与源数相同,就输出目标进制.
这题的坑点太多了,开始的时候没有用二分,直接从2开始循环来做,有三个点过不去,查了资料之后.
重新写了一遍代码.
1.用二分法是如何保证找出来的进制是最小的?
明确一点,如果为目标字符是二位以上的,那么不同进制转换出来的目标数一定不相同,且目标数随进制的增大而增大.
如果目标字符只有一位,那就要注意了,转换的时候targetNum=targetN[0]*jinzhi^0=target[0],你会发现目标数不随进制的增大而改变.
举个例子,3 3 1 10,tag=1表示第一个3是10进制的,求第二个3的进制,显而易见,第二个3的进制可以是4,5,6,7,8,9,10,11......
因此必须在二分之前解决这种情况
当然这个例子比较特殊,如果源字符和目标字符不相同,比如 3 5 1 10,那你会发现,无论是几进制,这两个数都不会相同.原理还是这条公式targetNum=targetN[0]*jinzhi^0=target[0].
因此讨论清楚了,区分目标字符数是一位或者二位的来解决.
2.为什么要用long long int ?
题意中说明了 源数中出现的最大字符是z,也就是35,源数最大的位数是10.虽然没有说radix的范围,我们就假设radix只有35
那么我们做个估计,假设源字符是zzzzzzzzzz,大概是 35*35^9=35^10<40^10=4^10*10^10 可以估计源数肯定超过10个0,int是存不下的.
并且,zzzzzzzzzz 10 1 35 在这个例子中,目标数等于目标进制等于源数的大小.因此目标进制和目标数也必须声明为long long int.
3.二分法的上界下界 ?
上界只要比源数大1,那么一定能够满足了.
下界要比目标字符中的任何一位上的数大1.
假设目标字符是 ab1 他不可能是2进制的,因为2进制只有两个数01.因此ab1至少是12进制的.
4.这一点我尚存疑惑.因为不知道超出long long int范围之后sum的值究竟是如何变化的,我不确定返回的sum一定是个负数.
在枚举目标进制计算目标数的时候,目标数的大小有可能超出long long int的范围,这时候返回的sum可能是一个负数,如果你不加判断,那么会导致你返回的值一直比源数小,程序会让low=mid+1,然后继续计算,导致目标数越来越大,我们知道,源数一定是在long long int范围内的,既然目标数在目标进制下已经超出long long int范围了,应该要让high=mid-1来缩小目标数来接近源数才对.
5.边界条件
1 1 2 2 或者1 1 1 2 这种例子,必须输出2.
- PAT_1010: Radix
- PAT_1010. Radix
- pat_1010
- Radix
- Radix
- radix tree
- Radix sort
- Radix Sort
- radix sort
- Radix Sort
- Radix TRee
- radix-sort
- radix sort
- 1010.Radix
- pat1010 Radix
- 1010. Radix
- 1010. Radix
- radix sort
- 极光推送
- github上操作部署
- 递归递推练习G小银呀考不过四级
- Java生成PDF的实现。
- 生活点滴
- PAT_1010. Radix
- Android探索之旅(第十一篇) 探索一种更轻,更便捷的操作数据库的库
- DOM--基础
- 国际化中,资源字符串中使用translatable声明不用翻译成其他语种
- 爬虫之标签定位记录
- 理解Docker技术
- computerdatabase项目中的监控数据收集
- 最大似然估计
- logback 每天生成和大小生成 冲突 TimeBasedRollingPolicy SizeBasedTriggeringPolicy