求二分解法

cstur4 2012-10-05 04:40:55
1010. Radix (25)
时间限制
400 ms
内存限制
32000 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

OJ地址:http://pat.zju.edu.cn/contests/pat-practise/1010

穷举超时了
...全文
661 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
huangxy10 2012-10-06
  • 打赏
  • 举报
回复
radix
huangxy10 2012-10-06
  • 打赏
  • 举报
回复
index估计也得用string来模拟。
huangxy10 2012-10-06
  • 打赏
  • 举报
回复
有一个测试用例的答案超过了int型能表示的范围了,感觉让人无能为力了,二分搜索也搞不定了。
。。。

#include <iostream>
#include <string>
#include <strstream>
#include <cmath>
using namespace std;

int ToInt( char ch ){
if( isdigit(ch) ) return ch-'0';
else if( islower( ch ) ) return ch-'a'+10;
return 0;
}

char ToChar( int num){
if( num<10) return num+'0';
else if( num<36) return num-10+'a';
return 0;
}

//36进制加法
string Add( const string & str1, const string & str2)
{
int len1=str1.size();
int len2=str2.size();
if(len1==0) return str2;
if(len2==0) return str1;
int len = len1>len2?len1:len2;
string rst;
rst.resize(len);
int carry = 0;
while(len>=1)
{
int c=0;
if( len1>=1&&len2>=1){
c = carry + ToInt(str1[len1-1])+ToInt(str2[len2-1]);
}
if( len1>=1&&len2<1){
c = carry + ToInt(str1[len1-1]);
}
if( len1<1&& len2>=1){
c = carry + ToInt(str2[len2-1]);
}
rst[--len]= ToChar(c%36);
carry = c/36;
len1--;
len2--;
}
if( carry >=1 )
return ToChar(carry)+rst;
else
return rst;
}

//36进制乘法
string Mul(const string &str1,char ch){
int carry = 0;
int len1 = str1.size();
string rst;
rst.resize(len1);
while( len1>=1 ){
int c = carry + ToInt(str1[len1-1])*ToInt(ch);
rst[--len1] = ToChar( c%36 );
carry = c/36;
}
if( carry>=1)
return ToChar(carry) + rst;
else
return rst;
}

string Mul( string &str1, string &str2){
int len1=str1.size();
int len2=str2.size();
string rst;
int k=0;
while(len2>=1){
string temp = Mul(str1, str2[len2-1]);
for( int i=0; i<k;i++)
temp.push_back('0');
k++;
rst = Add( rst, temp);
len2--;
}
return rst;
}

//去掉前面的0
string DeleteZero(const string &str){
int len= str.size();
int k=0;
while(k<len){
if( str[k]!='0' ){
break;
}
k++;
}
if( k==0 )
return str;
else if( k==len )
return string("0");
else
return str.substr(k,len-k);
}

//转换到36进制
string Convert(const string &str, string &radix){
int len = str.size();
string rst;
string multiplier = "1";
while(len>=1){
string m = Mul(multiplier,str[len-1]);
rst = Add(rst, m);
multiplier = Mul(multiplier,radix);
len--;
}
return DeleteZero(rst);
}

string ToString(int num){
strstream ss;
ss <<num;
string str;
ss >> str;
return str;
}

string Convert(const string &str, int radix){
if( radix < 36 ){
int len = str.size();
string rst;
string multiplier = "1";
while(len>=1){
string m = Mul(multiplier,str[len-1]);
rst = Add(rst, m);
multiplier = Mul(multiplier,ToChar(radix));
len--;
}
return DeleteZero(rst);
}
else{
string radix_10 = ToString( radix );
string radix_36 = Convert( radix_10, 10);
return Convert(str, radix_36);
}
}

int CheckRadix( string str){
int len = str.size();
int max =0;
for( int i=0; i<len; i++)
if( ToInt(str[i]) >= max )
max = ToInt(str[i])+1;
return max;
}

bool Cmp( string str1, string str2){
int len1= str1.size();
int len2 = str2.size();
if( len1>len2 )
return true;
if( len2>len1)
return false;
if( len1 == len2 ){
for( int i=0; i<len1; i++){
if(ToInt(str1[i])>ToInt(str2[i]))
return true;
if(ToInt(str1[i])<ToInt(str2[i]))
return false;
}
}
return false;
}

int BSearch(int low, int high, string num2, string target){

int flag = 0;
int mid = 0;
string tmp;
while(low<= high ){
mid = (low + high)/2;
tmp = Convert( num2, mid);
if( tmp == target ){
high = mid-1;
flag = mid;
}
else if( Cmp(tmp,target) )
high = mid - 1;
else
low = mid + 1;
}

if( flag ){
return flag;
}
else
return -1;
}

int main()
{
//freopen("out.txt","w",stdout);
string num1,num2;
cin>>num1>>num2;
num1 = DeleteZero(num1);
num2 = DeleteZero(num2);
int tag,radix;
cin>>tag>>radix;
if( tag==2 ){
string num = num1;
num1 = num2;
num2 = num;
}

if( CheckRadix( num1 ) > radix ){
cout <<"Impossible"<<endl;
return 0;
}

string radix_str = ToString( radix);
string radix_str_36 = Convert( radix_str, 10 );
string num1_36 = Convert( num1,radix_str_36);
int small = CheckRadix( num2 );
string r = ToString(small);
r = Convert( r, 10 );

/*string num2_36 = Convert( num2,r);
small = (int)pow((double)36, (double)(num1_36.size()/num2.size()));
r = ToString( small );
r = Convert( r, 10 );*/
/*while(1){
string num2_36 = Convert( num2,r);

if( num1_36 == num2_36 ){
cout << small <<endl;
break;
}

if( Cmp(num2_36,num1_36) ){
cout <<"Impossible"<<endl;
break;
}

if( num2_36.size() == 1 && r>num2_36 ){
cout <<"Impossible"<<endl;
break;
}

r = Add( r,"1");
small++;

}*/
int rst = BSearch( small, 0x4fffffff, num2, num1_36);
if( rst== -1 )
cout <<"Impossible"<<endl;
else
cout <<rst<<endl;

return 0;
}
FancyMouse 2012-10-06
  • 打赏
  • 举报
回复
>穷举超时了
我第一感觉是代码写扯,直接死循环了。
huangxy10 2012-10-05
  • 打赏
  • 举报
回复
需要找最小的,不好二分。
1,本身的数字可以决定该数的最小进制。
2,如果未知数的位数比已知数的位数大,则要找的进制应该小于已知数的进制;
3,可以通过已知数转换成十位的最后一位排除掉很多不可能的情况,
计算某数在十进制下的最后一位很很快的。

33,008

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧