NOIP2006普及组 Jam的计数法
普及组重要的模拟题。附上题目链接 https://www.luogu.org/problem/show?pid=1061 (写水题题解算是巩固提醒自己细心吧qwq)
样例输入:
2 10 5 bdfij
样例输出:
bdghi
bdghj
bdgij
bdhij
befgh
这题把数字转换成字符。指定一个区间[L,R],使用其中的字符作为数字使用。
拿样例数据来举例,L=2 R=10,则区间为
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
b | c | d | e | f | g | h | i | j |
起始数字为bdfij,要求依次输出后面的5个数字。输出下一个数字就要对这个数字的最低一位进行进位,如果这个数字超出了区间右边界R,则向高一位进位。
bdfij最低一位是j,进一变成k,k对应的数字11超出了右边界R=10,向高一位进位。i进一变成j,但是如果i变成j那么最后一位就不能再为j了(根据题意,数字中的字符没有重复,且从左到右字典序依次增大),那么这时候再向高一位进位,f变成g,剩余h,i,j可以给前两位进行进位。修改字符串。bdfij变成了bdghi,输出然后从最后一位继续做一遍。
代码实现:
1 var 2 s,t,n:longint; //s为边界L,t为边界R 3 str:string; 4 function w(ch:char):longint; //函数:返回字符对应的编号 5 begin 6 exit(ord(ch)-ord('a')+1); 7 end; 8 function dw(n:longint):char; //函数:返回编号对应的字符 9 begin 10 exit(chr(n+ord('a')-1)); 11 end; 12 procedure doit(c:longint); 13 var 14 i,last:longint; 15 begin 16 if c>5 then halt; //输出5次后退出程序 17 for i:=length(str) downto 0 do //从最低位开始 18 begin 19 if i=0 then //处理特殊情况 20 begin 21 last:=i; 22 break; 23 end; 24 if w(str[i])+1+length(str)-i>t then continue //如果进位后超出边界R则向高一位继续 25 else 26 begin 27 last:=i; //不超出边界,last记录当前所在位数 28 break; 29 end; 30 end; 31 str[last]:=dw(w(str[last])+1); //进一位 32 for i:=last+1 to length(str) do //处理剩余的位数 33 str[i]:=dw(w(str[i-1])+1); 34 writeln(str); //输出 35 doit(c+1); //继续 36 end; 37 begin 38 readln(s,t,n); 39 readln(str); 40 doit(1); 41 end.