A1010 Radix(进制转换+二分)

本文介绍了一种解决特定进制数转换问题的算法,通过枚举和二分搜索技术,寻找并验证未知数的最小可能进制。讨论了算法实现细节,包括映射表的初始化、十进制转换函数、比较函数以及二分搜索函数的设计,适用于解决复杂的数据转换挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

给定字符串N1,N2和整数tag,radix,tag=1,代表N1为radix进制数,tag=2代表N2为radix进制数,求N1和N2中那个未知进制数是否存在,若存在求出满足条件的最小进制。

本题代码参考算法笔记,具体函数功能在注释中已表明,要注意的是:
1.暴力枚举会超时
2.书中默认题目中的数转换为十进制时不会超过long long
3.注意代码中进制上界和下界的求取

本题步骤较多,比较容易做错

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
char N1[20],N2[20],temp[20];
int Map[256];//映射表0~9,a~z
LL inf=(1LL<<63)-1;//这里为算法笔记中默认那个数转换为10进制后不超过long long,所以设置了一个上限值防止溢出
int tag,radix;
void init()//将0~9,a~z映射到0~35
{
    for(char i='0';i<='9';i++)
        Map[i]=i-'0';
    for(char i='a';i<='z';i++)
        Map[i]=i-'a'+10;
}

LL convertNum10(char a[],LL radix,LL t)//将a转换为10进制,t为上界
{
    int len=strlen(a);
    LL ans=0;
    for(int i=0;i<len;i++)
    {
        ans=ans*radix+Map[a[i]];
        if(ans<0||ans>t) return -1;
    }
    return ans;
}

int cmp(char N2[],LL radix,LL t)//N2的十进制与t比较
{
    LL num=convertNum10(N2,radix,t);
    if(num<0) return 1;//溢出,N2大于t
    if(num>t) return 1;
    else if(num==t) return 0;
    else return -1;
}

LL binarySearch(char N2[],LL left,LL right,LL t)//二分求解N2的进制
{
    LL mid;
    while(left<=right)
    {
        mid=(left+right)/2;
        LL flag=cmp(N2,mid,t);
        if(flag==-1) left=mid+1;//进制越大,将其转换为十进制的结果更大
        else if(flag==1) right=mid-1;
        else return mid;
    }
    return -1;
}

int findLastDigit(char N2[])//求最大的数位
{
    int len=strlen(N2);
    int ans=-1;
    for(int i=0;i<len;i++)
    {
        ans=max(ans,Map[N2[i]]);
    }
    return ans+1;//最大数位为ans,故ans+1为数位底线
}

int main()
{
    init();
    scanf("%s%s%d%d",N1,N2,&tag,&radix);
    if(tag==2)//N1放置确定进制的数
    {
        strcpy(temp,N2);
        strcpy(N2,N1);
        strcpy(N1,temp);
    }
    LL t=convertNum10(N1,radix,inf);
    LL low=findLastDigit(N2);
    LL high=max(low,t)+1;//eg.t=30,那么N2最多30进制,此时在N2为1的时候十进制为30,若更大,则一定大于30
    LL ans=binarySearch(N2,low,high,t);
    if(ans==-1) printf("Impossible\n");
    else printf("%lld\n",ans);
    return 0;

}

<think>好的,我现在需要解决用户的问题,即计算输入的学生学号名单中有多少学生进入决赛。首先,用户给出的例子是输入一个用英文逗号分隔的学号列表,输出数量。但看起来用户的输入示例中,学号之间的分隔符有些问题,比如有些是用逗号分隔,有些是空格,这可能是个需要注意的地方。 首先,我需要明确如何正确解析输入的字符串。用户提供的示例输入是“‘J0806’,‘J0723’,‘B0605’,‘S0901’,‘Z0403’ ‘A1010’”,这里后面的“Z0403”和“A1010”之间是空格而不是逗号。这可能意味着用户在实际输入中可能存在分隔符不一致的情况,比如混合使用逗号和空格。不过,根据题目描述,输入应该用英文逗号隔开,所以这可能是一个示例中的错误,或者需要处理这种情况。 接下来,正确的处理步骤应该是: 1. 接收输入字符串。 2. 清理输入中的多余字符,比如单引号。 3. 分割字符串成学号列表,可能需要处理多种分隔符的情况。 4. 统计列表的长度,即为学生人数。 但根据用户提供的示例输出,正确的答案是6,而示例输入中有6个学号,虽然分隔符有误。所以可能用户希望我们假设输入中的分隔符都是正确的,即使用逗号分隔,可能示例中的空格是输入错误。或者需要处理这种情况,例如将多个分隔符统一处理。 可能的解决方案有两种: - 方法一:替换所有非逗号分隔符为逗号,然后分割。 - 方法二:使用正则表达式分割字符串,处理多种分隔符。 但考虑到题目描述中明确说明“用英文逗号隔开”,可能用户希望我们严格按照逗号分割,而示例中的空格可能只是笔误。因此,正确的做法是忽略示例中的空格,或者处理这种情况。 但为了确保代码的健壮性,可能需要处理输入中的各种分隔符问题,例如多余的引号、空格等。例如,用户提供的输入示例中的学号被单引号包围,可能需要先去除这些引号,然后分割。 具体步骤: 1. 输入字符串处理:去除所有单引号,替换可能的其他分隔符(如空格)为逗号。 2. 使用split(',')分割字符串,得到学号列表。 3. 过滤掉空字符串(如果有的话)。 4. 统计列表长度。 例如,输入示例中的字符串处理后的学号列表应该是['J0806', 'J0723', 'B0605', 'S0901', 'Z0403', 'A1010'],共6个元素。 在Python中,可以用以下步骤实现: - 去除输入中的所有单引号:使用replace("'", "")。 - 替换空格为逗号:replace(' ', ',')。 - 分割字符串:split(',')。 - 过滤空字符串:列表推导式或filter函数。 然后统计长度即可。 需要注意的情况包括: - 输入中有多余的空格或其他分隔符。 - 学号之间有多个逗号导致空字符串。 - 学号本身可能包含其他字符,但题目中假设学号是正确的。 因此,代码的大致结构应该是: s = input().replace("'", "").replace(' ', ',') lst = [x for x in s.split(',') if x] print(len(lst)) 这样处理后的输入示例可以得到正确的6个学生。 总结,用户的问题核心在于正确解析输入字符串中的学号数量,需要处理分隔符和引号的问题。代码需要健壮地处理这些情况,确保统计准确。</think>### 分步解答 #### 方法一:字符串处理法(兼容分隔符错误) ```python # 输入示例(注意原题输入中有混合分隔符): # 'J0806','J0723','B0605','S0901','Z0403' 'A1010' # 1. 去除所有单引号和空格,统一为逗号分隔 input_str = input().replace("'", "").replace(" ", ",") # 2. 分割字符串并过滤空值 student_list = [x for x in input_str.split(",") if x] # 3. 输出结果 print(len(student_list)) ``` #### 方法二:正则表达式法(更健壮) ```python import re # 使用正则表达式匹配所有大写字母+数字的组合 student_list = re.findall(r'\b[A-Z]\d{4}\b', input()) print(len(student_list)) ``` ### 执行示例 ``` 输入: 'J0806','J0723','B0605','S0901','Z0403' 'A1010' 输出: 6 ``` ### 关键点解析 1. **输入清洗**:原题输入存在混合分隔符(逗号和空格),需要统一处理 - `replace("'", "")` 清除干扰符号 - `replace(" ", ",")` 统一分隔符 2. **空值过滤**:分割后可能出现空字符串,需用列表推导式 `if x` 过滤 3. **正则优势**:方法二直接匹配学号格式(大写字母+4位数字),避免分隔符问题 4. **学号格式**:题目中学号均为类似`J0806`的格式(1个大写字母+4位数字) 两种方法均能正确处理原题中的异常分隔符情况,正则表达式法在输入格式复杂时更具健壮性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值