http://acm.pku.edu.cn/JudgeOnline/problem?id=1196

Секретные сообщения между Санта-Клаусом и его маленькими помощниками обычно кодируются так называемым 25-языком. В этом языке используется 25-алфавит, который совпадает с латинским алфавитом с одним исключением – в нем отсутствует буква 'Z', то есть 25-алфавит содержит 25 латинских букв от 'A' до 'Y' в том же порядке, что и латинский алфавит. Каждое слово в 25-языке состоит ровно из 25 различных букв. Слово записывается в таблице размера 5x5, строка за строкой. Например, слово ADJPTBEKQUCGLRVFINSWHMOXY будет записано так:

A D J P T
B E K Q U
C G L R V
F I N S W
H M O X Y

Правильным словом 25-языка считается слово, буквы которого в каждой строке и каждом столбце расположены по возрастанию их номера в алфавите. Поэтому слово ADJPTBEKQUCGLRVFINSWHMOXY является правильным словом, а слово ADJPTBEGQUCKLRVFINSWHMOXY - нет (возрастающий порядок нарушается во втором и третьем столбцах).

Лексикон Санта-Клауса состоит из всех правильных слов 25-языка. Слова расположены в возрастающем лексикографическом порядке и пронумерованы, начиная с единицы. Например, в лексиконе Санта-Клауса слово ABCDEFGHIJKLMNOPQRSTUVWXY имеет номер 1, а слово ABCDEFGHIJKLMNOPQRSUTVWXY имеет номер 2. Во втором слове, по сравнению с первым, буквы U и Т поменялись местами.

К сожалению, лексикон Санта-Клауса огромен. Напишите программу, которая определяет порядковый номер по заданному слову из лексикона Санта-Клауса, а по заданному порядковому номеру определяет соответствующее слово. В лексиконе Санта-Клауса не больше 231 слов.

ВВОД

Входной файл имеет имя twofive.in и состоит из двух строк. Первая строка содержит один из символов 'W' или 'N'. Если первая строка содержит 'W', тогда вторая строка содержит правильное слово 25-языка, то есть строку из 25 символов. Если первая строка содержит 'N', то вторая строка содержит порядковый номер существующего слова 25-языка.

ВЫВОД

Выходной файл имеет имя twofive.out. Если вторая строка входного файла содержит слово 25-языка, то единственная строка выходного файла должна содержать его порядковый номер в лексиконе Санта-Клауса. Если вторая строка входного файла содержит число, то единственная строка выходного файла должна содержать слово 25-языка с этим номером.

ПРИМЕРЫ ВВОДА И ВЫВОДА

twofive.in
W
ABCDEFGHIJKLMNOPQRSUTVWXY

twofive.out
2

twofive.in
N
2

twofive.out
ABCDEFGHIJKLMNOPQRSUTVWXY

Код:
const 
 states=6*6*6*6*6; 
var 
 num:longint; 
 c:char; 
 str:string; 
 lx,ly:array[ 1..25 ] of integer; 
 state:array[ 0..5 ] of longint; 
 f:array[ 0..states-1 ] of longint; 

function calc(l:integer):longint; 
 var i,a,b,c:longint; 
 begin 
   a:=state[ 1 ]; 
   for i:=2 to 5 do a:=a*6+state[ i ]; 
   if f[ a ]<0 then begin 
     b:=0;c:=lx[ l ]; 
     if c<0 then begin 
       for i:=1 to 5 do 
         if state[ i ]<state[ i-1 ] then 
         begin 
           inc(state[ i ]); 
           inc(b,calc(l+1)); 
           dec(state[ i ]); 
         end 
     end else 
       if (state[ c-1 ]>state[ c ]) and (state[ c ]+1=ly[ l ]) then 
       begin 
         inc(state[ c ]); 
         inc(b,calc(l+1)); 
         dec(state[ c ]); 
       end; 
     f[ a ]:=b; 
   end; 
   calc:=f[ a ]; 
 end; 

function numconts:longint; 
 begin 
   fillchar(f,sizeof(f),$ff); 
   fillchar(state,sizeof(state),0); 
   state[ 0 ]:=5; 
   f[ states-1 ]:=1; 
   numconts:=calc(1); 
 end; 

function wordtonum:longint; 
 var i,j,k,ch:integer; 
 begin 
   fillchar(lx,sizeof(lx),$ff); 
   num:=1; 
   for i:=1 to 5 do 
     for j:=1 to 5 do 
       begin 
         ch:=ord(str[ (i-1)*5+j ])-64; 
         for k:=1 to ch-1 do 
           if lx[ k ]<0 then begin 
             lx[ k ]:=i; 
             ly[ k ]:=j; 
             inc(num,numconts); 
             lx[ k ]:=-1; 
           end; 
         lx[ ch ]:=i; 
         ly[ ch ]:=j; 
       end; 
   wordtonum:=num; 
 end; 

procedure numtoword; 
 var i,j,k:integer; 
     out:array[ 1..25 ] of char; 
     l:longint; 
 begin 
   fillchar(lx,sizeof(lx),$ff); 
   for i:=1 to 5 do 
     for j:=1 to 5 do 
       for k:=1 to 25 do 
         if lx[ k ]<0 then begin 
           lx[ k ]:=i; 
           ly[ k ]:=j; 
           l:=numconts; 
           if num>l then dec(num,l) 
           else break; 
           lx[ k ]:=-1; 
         end; 
   for i:=1 to 25 do out[ (lx[ i ]-1)*5+ly[ i ] ]:=chr(64+i); 
   for i:=1 to 25 do write(out[ i ]); 
   writeln; 
 end; 

begin 
 //assign(input,'twofive.in'); 
 //assign(output,'twofive.out'); 
 //reset(input); 
 //rewrite(output); 
 readln(c); 
 if c='W' then begin 
   readln(str); 
   writeln(wordtonum); 
 end else begin 
   readln(num); 
   numtoword; 
 end; 
 //close(input); 
 //close(output); 
end.