1010. Radix (25)(***二分法)

来源:互联网 发布:创作音乐软件 编辑:程序博客网 时间:2024/06/06 09:21

1010. Radix (25)

时间限制
400 ms
内存限制
65536 kB
代码长度限制
16000 B
判题程序
Standard
作者
CHEN, Yue

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
题意:给定两个数,其中单个位置上的数值范围可以为 [0-z]。指定其中一个数的进制,试确定是否存在可能的进制让两数的实际值相等

自己写的顺序搜索,结果最后超时

#include<iostream>#include<cstring>using namespace std;char n1[11];char n2[11];int tag;long long int radix; int main(){//freopen("in.txt","r",stdin);cin>>n1>>n2>>tag>>radix;long long int a=0,b=0;if(tag==1){for(int i=0;i<=strlen(n1)-1;++i){if(n1[i]>='a' && n1[i]<='z')a=radix*a+n1[i]-'a'+10;elsea=radix*a+n1[i]-'0';}for(int i=1;i<=a+1;++i)//n2的最大进制一定小于n1的值 {b=0;for(int j=0;j<=strlen(n2)-1;++j){if(n2[j]>='a' && n2[j]<='z'){if(n2[j]-'a'+10>=i)break;b=i*b+n2[j]-'a'+10;}else{if(n2[j]-'0'>=i)break;b=i*b+n2[j]-'0';}}if(a==b){cout<<i;return 0;}}cout<<"Impossible";return 0;}else{for(int i=0;i<=strlen(n2)-1;++i){if(n2[i]>='a' && n2[i]<='z')b=radix*b+n2[i]-'a'+10;elseb=radix*b+n2[i]-'0';}for(int i=1;i<=b+1;++i){a=0;for(int j=0;j<=strlen(n1)-1;++j){if(n1[j]>='a' && n1[j]<='z'){if(n1[j]-'a'+10>=i)break;a=i*a+n1[j]-'a'+10;}else{if(n1[j]-'0'>=i)break;a=i*a+n1[j]-'0';}}if(a==b){cout<<i;return 0;}}cout<<"Impossible";return 0;}return 0;} 


意几点:

1. 一定都要用Long long int,不然会错很多case;

2. 注意计算radix的值时,有可能会发生溢出,得到的result结果为负数,此时应该减少radix的值;

3. 不能使用简单的顺序搜索算法,会超时;应该使用二分法搜索;

4.除了只有一位数时候可能出现多个解,其余情况均只有一个解。

5.二分法搜索能够保证得到的结果唯一并且正确。

#include<iostream>#include<cstring> using namespace std;char n1[15];char n2[15];int tag;long long int radix;long long int minradix=0,maxradix;//分别表示二分查找进制的二个边界int change_num(char c);//转换成0-36数字 long long int calnum(char charray[],long long int rad);//计算给出进制,变换成十进制的值 int main(){//freopen("in.txt","r",stdin);cin>>n1>>n2>>tag>>radix;if(tag==2){char tmp[11];strcpy(tmp,n1);strcpy(n1,n2);strcpy(n2,tmp);}for(int i=0;i<strlen(n2);++i){if(change_num(n2[i])>minradix)minradix=change_num(n2[i]);}++minradix;long long int valuea=calnum(n1,radix);maxradix=valuea+1;//正整数,n2至少是1,所以n2的最大进制为n1+1(重要) while(minradix<=maxradix)//二分法 {long long int center=(minradix+maxradix)/2;long long int valueb=calnum(n2,center);if(valueb==-1 || valueb>valuea)//=-1说明进制选大了 {maxradix=center-1;}else if(valueb<valuea){minradix=center+1;} else if(valuea==valueb){cout<<center;return 0;}}cout<<"Impossible";return 0;} int change_num(char c){if(c>='0' && c<='9')return c-'0';elsereturn c-'a'+10; } long long int calnum(char charray[],long long int rad){long long int result=0;for(int i=0;i<strlen(charray);++i){result=rad*result+change_num(charray[i]);if(result<=0)//(很重要)注意计算radix的值时,有可能会发生溢出,得到的result结果为负数,此时应该减少radix的值return -1;}return result;}



原创粉丝点击