信息学奥赛一本通题目解析:1936:【06NOIP普及组】Jam的计数法

【题目描述】

Jam是个喜欢标新立异的科学怪人。他不使用阿拉伯数字计数,而是使用小写英文字母计数,他觉得这样做,会使世界更加丰富多彩。在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文字母按原先的顺序,排在前面的字母小于排在它后面的字母。我们把这样的“数字”称为Jam数字。在Jam数字中,每个字母互不相同,而且从左到右是严格递增的。每次,Jam还指定使用字母的范围,例如,从2到10,表示只能使用{b,c,d,e,f,g,h,i,j}这些字母。如果再规定位数为5,那么,紧接在Jam数字“bdfij”之后的数字应该是“bdghi”。(如果我们用U、V依次表示Jam数字“bdfij”与“bdghi”,则U<V,且不存在Jam数字P,使U<P<V)。你的任务是:对于从文件读入的一个Jam数字,按顺序输出紧接在后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。

【输入】

有2行,第1行为3个正整数,用一个空格隔开:

s t w (其中s为所使用的最小的字母的序号,t为所使用的最大的字母的序号。w为数字的位数,这3个数满足:1≤s第2行为具有w个小写字母的字符串,为一个符合要求的Jam数字。

所给的数据都是正确的,不必验证。

【输出】

最多为5行,为紧接在输入的Jam数字后面的5个Jam数字,如果后面没有那么多Jam数字,那么有几个就输出几个。每行只输出一个Jam数字,是由w个小写字母组成的字符串,不要有多余的空格。

【输入样例】

2 10 5
bdfij

【输出样例】

bdghi
bdghj
bdgij
bdhij
befgh

【解题思路】

解题思路如下:

  1. 读取输入:读取输入的最小字母序号 start、最大字母序号 end 和数字的位数 len,以及当前的 Jam 数字 num

  2. 外层循环:使用一个循环控制输出的 Jam 数字数量,最多输出 5 个。

  3. 内层循环:从 Jam 数字的最后一个字符开始向前枚举可能的变动位。

  4. 计算最大值:对于每个位置 j,计算该位置可以取到的最大值 tmp

  5. 判断可行性:检查当前位 num[j] 加 1 是否小于等于 tmp,如果是,则找到了下一个Jam数字的当前位。

  6. 更新Jam数字:将 num[j] 加 1,并更新 j 之后的所有位,确保 Jam 数字严格递增。

  7. 输出Jam数字:输出更新后的 Jam 数字。

  8. 结束条件:如果已经找到下一个Jam数字,则跳出内层循环,继续寻找下一个。

  9. 重复过程:重复步骤 3 到 8,直到输出了 5 个 Jam 数字或者已经没有更多的 Jam 数字可以生成。

【代码实现】

#include<bits/stdc++.h>
using namespace std;

char num[35]; // 存储输入的Jam数字

int main() {
    int start, end, len;// 读取字母范围的起始和结束序号,以及数字的位数
    cin>>start>>end>>len;
    cin>>num;// 读取输入的Jam数字字符串

    // 尝试输出5个Jam数字
    for (int i = 1; i <= 5; i++) {
        // 从Jam数字的最后一个字符开始向前枚举变动位
        for (int j = len - 1; j >= 0; j--) {
            int tmp = 'a' + (end - (len - j)); // 计算当前位可以取到的最大值
            // 判断当前位加1是否小于等于tmp,即是否可行
            if (num[j] + 1 <= tmp) {
                num[j] += 1; // 将当前位加1
                // 对齐后续位,确保Jam数字严格递增
                for (int k = j + 1; k < len; k++) {
                    num[k] = num[j] + (k - j);
                }
                cout<<num<<endl;// 输出新的Jam数字
                break; // 找到下一个Jam数字后,跳出内层循环
            }
        }
    }
    return 0;
}

  • 14
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值