lalalala


私信TA

用户名:zhangshuo

访问量:161482

签 名:

像狗一样的学习,像绅士一样地玩耍。

等  级
排  名 7
经  验 31290
参赛次数 10
文章发表 201
年  龄 12
在职情况 学生
学  校 芜湖市第十一中学
专  业

  自我简介:

今日懒惰流下的口水,将会成为明日里伤心的泪水。

解题思路:





注意事项:

主要是c++,其次还有几个java写法,不过思路大致一样





参考代码:

本人蒟蒻,不好请原谅

方法:先从低位往高位找到一个可以加的位数,然后把后面的数变为前面那个数加1

建议先从主程序开始看。

#include<cstdio>#include<iostream>#include<string>using namespace std;int a[26],a1,a2,w;bool add()//加,布尔是用来判断当前是不是最大的数{   int g=0;   for (int i=1;i<=w;i++)
  {        if (a[i]!=a2-i+1) {g=i; break;}        //判断该个数是否为当前位置最大的数如果是则判断下一个数
       //直到找到不是最大的数的位置。
  }   if (g==0) return true;//如果每个位都是最大的数则返回退出
  a[g]++;//当前位加1
  for (int i=g-1;i>=1;i--)
  {
       a[i]=a[i+1]+1;//把后面的数变为前面那个数加1
  }   return false;
}void write()//输出{    for (int i=w;i>1;i--)      printf("%c",a[i]+97+a1-1);    printf("%c\n",a[1]+97+a1-1);
}int main(){    scanf("%d%d%d\n",&a1,&a2,&w);//输入不解释
   a2-=a1;//求他可以使用的数字数量。
   string s;
   getline(cin,s);    
   for (int i=w-1;i>=0;i--)//从低位往高位存
   {
       a[w-i]=s[i]-97-a1+1;//输入。减a1加1可以方便些,可以不加。
   }    for (int i=1;i<=5;i++)//循环输入5个数
   {        if (add()) break;//加1
       write();//输出
   }
}


评论

还没有评论

评论



这里写题解

varl,r,w,i,j,sum:longint;
s:string;
hh,hhh,ch:char;begin
 readln(l,r,w);
 readln(s);
 hh:=chr(96+l);{可选字母的最小值}
 hhh:=chr(96+r);{可选字母的最大值}
 repeat
   for i:=w downto 1 do begin
 ch:=chr(ord(s[i])+1);{枚举s串每个字母在字母表中的下一个字母}
 if (ch>=hh)and(ch<=hhh)and(pos(ch,s)=0) then begin{ch在可选范围且在原串没有出现}
   s[i]:=ch;{把符合条件的字母改为ch}
   //write(s[i],' ');
    break;  end;end;for j:=i+1 to w do begin{从修改字母的下一位开始,按字母表顺序修改}
 s[j]:=chr(ord(s[j-1])+1);end;
 inc(sum);
 writeln(s);  until sum=5;end.


评论

土间埋
这个真的强!!!!\n——十年树木百年树人

厉害

评论



分析:

这道题其实是输出一个字符串(可以把a看成1,b看成2,以此类推……)满足进制的后面连续5个字符串,这个进制是t+1进制(逢t进一),最小数是s(s没什么用)。不过有一个很奇怪的规定,就是后面的数一定要比前面的数大。

拿样例来看:bdfij

首先最后一位j已经不能再+1了,那就向前一位i进一,进一后变成j,后面的数要比前面的数大,所以j还要再向f进一,f进一变成g,满足了后面两个数都可以比前一个数大的条件,这时要求和原数只差1的数,倒数第二位就变成g+1=h,最后一位就变成h+1=i,结果就是bdghi。

实现的话就是先把最后一位+1,看有没有超过进制,如果没有,就直接输出,继续下一个+1,如果有,就把前面一位+1,再看有没有超出进制,没有的话把后面的数(最后一位)依次从前往后赋值成前一个数(字符)+1,输出,有的话重复上面的步骤,如果第一位进一满足不了后面的数比前面的数大的条件的话,就终止程序,否则输出5次就行了。

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>using namespace std;int main(){    int a,b,n,i2=0;    string s;    cin>>a>>b>>n>>s;    for(int i=1;i<=5;i++)
   {
       s[n-1]++;        for(int q=n-1;;q--)
       {            if(s[q]>b+96-i2)
           {
               s[q-1]++;                if(q==0) return 0;
           }            else
           {                for(int j=q+1;j<=n-1;j++)
               {
                   s[j]=s[j-1]+1;
               }                break;
           }
           i2++;
       }        cout<<s<<endl;
       i2=0;
   }    return 0;
}


评论

还没有评论

评论



这题其实跟另一个noip普及组的火星人有点相似。

我是现将字符转化成数字,就拿样例说:

转化前:b d f i j

转化后:2 4 6 9 10

然后把这串数字从最后一个往前找,找到第一个可以+1的位置,就拿转换后的:2 4 6 9 10说,从10开始,+1后不合法(超出了范围),然后到9,+1后不合法(10已经用过了),再往前找,找到6,+1后合法,所以+1,并将后面的所有数字重排一边,重复5次,就能得到结果,输出时再将数字转换成字符。

var
       a:array [1..26] of longint;
       bz:array [1..26] of boolean;//标记数组,true为用过,false为没用过
       f,l,n,i,j,count:longint;
       ch:char;procedure sort(x,y:longint);var
       i,c:longint;begin
       for i:=x to y do
               bz[a[i]]:=false;//预处理(关键)
       for i:=x to y do
       begin
               c:=a[i-1];                while bz[c]=true do//找到里a[i-1]最近的一个合法数
               begin
                       c:=c+1;                        if c>l then halt;                end;
               bz[a[i]]:=false;//标记数组处理
               bz[c]:=true;
               a[i]:=c;//变量处理
       end;end;begin
       fillchar(bz,sizeof(bz),false);//清空
       readln(f,l,n);        for i:=1 to n do
       begin
               read(ch);
               a[i]:=ord(ch)-96;//转换数字
               bz[a[i]]:=true;//改变标记数组
       end;
       count:=5;//循环五次
       while count>0 do
       begin
               dec(count);                for i:=n downto 1 do
               begin
                       if (a[i]+1<=l) and (bz[a[i]+1]=false) then//如果+1后合法
                       begin
                               bz[a[i]]:=false;//将原来的改为没用过
                               bz[a[i]+1]:=true;//讲现在的改为用过
                               a[i]:=a[i]+1;
                               sort(i+1,n);//将i后面的排序
                               break;//退出
                       end;                end;                for i:=1 to n do
                       write(chr(a[i]+96));//输出时转换为字符
               writeln;        end;end.


评论

还没有评论

评论



因字符复杂可先转为数组来解。

用b存入a的最大值并每次都从末尾开始尝试增加一个(若b=a则没有数值可变),同时将被增加的数之后的所有数变为最小。如此反复,可举出所有情况。

var s,t,w,m,n,i,j,k,count:longint;
   g:string;
   a,b:array[0..26]of longint;begin
 readln(s,t,w);
 readln(g);  for i:=1 to w do a[i]:=ord(g[i])-ord('a')+1;//string转array
 for i:=1 to w do b[i]:=t-w+i;//b的值只与i有关
 i:=w;  while (i>0)and(count<5) do
   begin
     if b[i]=a[i] then begin dec(i); continue; end;//无值可变化
     inc(a[i]);      for j:=i+1 to w do a[j]:=a[i]+j-i;//还原为最小
     for j:=1 to w do
       write(chr(a[j]+ord('a')-1));
     writeln;
     inc(count);
     i:=w;    end;end.

 


 

0.0分

0 人评分

  评论区

  • «
  • »