1010 Radix (25 分)

网友的,思路和我一样

#include <cstdio>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
using namespace std;
char tmp1[15],str1[15];
char tmp2[15],str2[15];
long long num1=0,num2=0; 
int flag;
typedef long long LL;
LL radix;
LL inf=(1LL<<63)-1;
 
long long convert(char str[],LL radix,LL t){
	long long num=0;
	for(int i=0;i<strlen(str);i++){
		if(str[i]>='0' && str[i]<='9'){
			num=num*radix+str[i]-'0';
		}
		else if(str[i]>='a' && str[i]<='z'){
			num=num*radix+(str[i]-'a'+10);
		}
	}
	if(num<0) return -1;
	return num;
} 
 
int findLargest(char str[]){
	int MAX=0;
	for(int i=0;i<strlen(str);i++){
		if(str[i]>='0' && str[i]<='9') MAX=max(MAX,str[i]-'0');
		else if(str[i]>='a' && str[i]<='z')	MAX=max(MAX,str[i]-'a'+10);
	}
	return MAX+1;
}
 
int main(){
	scanf("%s %s %d %d",tmp1,tmp2,&flag,&radix);
	if(flag==1){
		strcpy(str1,tmp1);
		strcpy(str2,tmp2);
	}
	else if(flag==2){
		strcpy(str1,tmp2);
		strcpy(str2,tmp1);
	}
    
	num1=convert(str1,radix,inf);
	long long l=0,r=400,mid;
	l=findLargest(str2);
	r=max(l,num1)+1;
	bool f=false;
	while(l<r){
		mid=(l+r)/2;
		long long tmp=convert(str2,mid,inf);
		if(tmp==-1) r=mid;
		else if(tmp==num1){
			printf("%lld\n",mid);
			f=true;
			break;
		}
		else if(tmp<num1) l=mid+1;
		else r=mid;
	}
	if(f==false) printf("Impossible\n");
	return 0;
}

我的代码

  1. 错误点:
    • 题意的意思和我们理解的不一样dst可以为任意合理的进制,不一定在1-36之间
    • 二分的时候left的取值最小为dst中的最大出现的数代表的进制
    • right的取值可以非常大,不会超过src的值,需要用到long long
#include<cstdio>
#include<iostream>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;

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

void swap(char*src,char*dst){
    char tmp[15];
    strcpy(tmp,src);
    strcpy(src,dst);
    strcpy(dst,tmp);
}

/*
// 18分,因为那个最大的right选小了
const int MAXN=1005;
int src_10[MAXN];
int src_len=0;
int dst_10[MAXN];
int dst_len=0;

void transBase(int*nums,int len_nums,int src_base_,int new_base_,int *res_,int &num_res_){
    int ans[MAXN];  // 存放商
    num_res_=0;
    while(len_nums>=1){
        int remain=0;
        int i=0;
        while(i<len_nums){
            remain=remain*src_base_+nums[i];
            ans[i]=remain/new_base_;
            remain=remain%new_base_;
            i++;
        }
        res_[num_res_++]=remain;
        i=0;
        while(i<len_nums&&ans[i]==0)i++;
        int new_len_nums=0;
        for(;i<len_nums;i++){
            nums[new_len_nums++]=ans[i];
        }
        len_nums=new_len_nums;
    }
}

void get10(char*src_,int src_base_,int *dst_10_,int &dst_len_){
    int n=strlen(src_);
    int nums[MAXN]; // 存放被除数
    int len_nums=0;
    for(int i=0;i<n;i++){
        nums[i]=getNum(src_[i]);
        len_nums++;
    }
    transBase(nums,len_nums,src_base_,10,dst_10_,dst_len_);
}
int strcmpSrcDst(int*src_,int src_len_,int*dst_,int dst_len_){
    if(src_len_<dst_len_){
        return -1;
    }
    else if(src_len_>dst_len_){
        return 1;
    }
    for(int i=src_len_-1;i>=0;i--){
        if(src_[i]>dst_[i]){
            return 1;
        }
        else if(src_[i]<dst_[i]){
            return -1;
        }
    }
    return 0;
}
int solve(char* src,char* dst,int src_base){
    int min_left=2;
    for(int i=0;i<strlen(dst);i++){
        int num=getNum(dst[i]);
        min_left=max(min_left,num+1);
    }
    src_len=dst_len=0;
    get10(src,src_base,src_10,src_len); // src转化成src_10
    
    int left=min_left,right=36;
    while(left<=right){
        int mid=(left+right)/2;
        get10(dst,mid,dst_10,dst_len);
        int cmp_res=strcmpSrcDst(src_10,src_len,dst_10,dst_len);
        if(cmp_res>0){
            left=mid+1;
            continue;
        }
        else if(cmp_res<0){
            right=mid-1;
            continue;
        }
        else{
            return mid;
        }
    }
    return -1;
}
*/

long long get10_long_long(char*src_,int src_base_){
    int n=strlen(src_);
    long long res_=0;
    for(int i=0;i<n;i++){
        res_=res_*src_base_+(long long)getNum(src_[i]);
    }
    // 坑点,dst不一定是36进制内的数
    if(res_<0){
        return -1;
    }
    return res_;
}

int solve_long_long(char* src,char* dst,int src_base){
    long long min_left=0;
    for(int i=0;i<strlen(dst);i++){
        int num=getNum(dst[i]);
        min_left=max(min_left,(long long)num);
    }
    min_left+=1;
    
    long long s_src_10=get10_long_long(src,src_base);
    
    long long left=min_left;
//     int right=100005;
    // 坑点,这里需要用到long long啊
    long long right=max(left,s_src_10)+1;
    
    while(left<=right){
        long long mid=(left+right)/2;
        long long s_dst_10=get10_long_long(dst,mid);
        if(s_dst_10==-1){
            right=mid-1;
        }
        else if(s_src_10>s_dst_10){
            left=mid+1;
            continue;
        }
        else if(s_src_10<s_dst_10){
            right=mid-1;
            continue;
        }
        else{
            // 二分找到的不一定是最小值,需要处理。
            mid--;
            while(mid>=min_left&&get10_long_long(dst,mid)==s_src_10){
                mid--;
            }
            mid=max(mid+1,min_left);
            return mid;
        }
    }
    return -1;
}



int main(){
    char src[15],dst[15];
    int tag,src_base;
    cin>>src>>dst>>tag>>src_base;
    if(tag==2){
        swap(src,dst);
    }
    int res_=solve_long_long(src,dst,src_base);
    if(res_==-1){
        printf("Impossible\n");
    }
    else{
        printf("%d\n",res_);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值