Editorial for Trật tự


Remember to use this editorial only when stuck, and not to copy-paste code from it. Please be respectful to the problem author and editorialist.
Submitting an official solution before solving the problem yourself is a bannable offence.

Lưu ý: Các code mẫu dưới đây chỉ mang tính tham khảo và có thể không AC được bài tập này

Code mẫu của RR

PROGRAM NK05ORDR;
CONST
  fi='';
  fo='';
VAR
  n:qword;
  m,k:longint;
  f1,f2:text;
Procedure Tinh;
Var
  a,x:qword;
  k1:longint;
Begin
  k1:=k; x:=0;
  a:=1; While a<k do a:=a*10;
  repeat
    a:=a div 10;
    x:=x+(k1-a)+1;
    k1:=k1 div 10;
  until k1=0;
  If x>m then begin n:=0; exit; end;
  n:=k;
  If m=x then exit;
  a:=1; While a<k do a:=a*10;
  repeat
    If a+m-x-1<k*10 then
      begin
        n:=a+m-x-1;
        m:=x;
      end
    else
      begin
        k:=k*10;
        x:=x+k-a;
        a:=a*10;
      end;
  until m=x;
End;
Procedure Solve;
Var
  t,i:integer;
Begin
  Assign(f1,fi); Reset(f1);
  Assign(f2,fo); Rewrite(f2);
  Readln(f1,t);
  For i:=1 to t do
  begin
    Readln(f1,k,m);
    If k=1 then
    begin
      If m=1 then n:=1 else n:=0;
    end
    else Tinh;
    Writeln(f2,n);
  end;
  Close(f1); Close(f2);
End;
BEGIN
  Solve;
END.

Code mẫu của khuc_tuan

const
  MAX_NUM = 1000000000;
  MAX_DIG = 30;

type
  TDecimal = record
    cnt: integer;
    d: array[-MAX_DIG..MAX_DIG] of integer;
  end;

procedure parse(l: longint; var d: TDecimal); 
var
  i: integer;
begin
  for i := -MAX_DIG to MAX_DIG do
    d.d[i] := 0;
  d.cnt := 0;
  while l > 0 do begin
    d.d[d.cnt] := l mod 10;
    l := l div 10;
    inc(d.cnt);
  end;
end;

procedure add(a, b: TDecimal; var c: TDecimal);
var
  r, i: integer;
begin
  parse(0, c);
  r := 0;
  i := 0;
  while (r <> 0) or (i < a.cnt) or (i < b.cnt) do begin
    r := r + a.d[i] + b.d[i];
    c.d[i] := r mod 10;
    r := r div 10;                                  
    inc(i);
  end;
  c.cnt := i;
end;

procedure sub(a, b: TDecimal; var c: TDecimal);
var
  r, i: integer;
begin
  parse(0, c);
  r := 0;
  i := 0;
  while (r <> 0) or (i < a.cnt) or (i < b.cnt) do begin
    r := r + a.d[i] - b.d[i];
    c.d[i] := (r + 100) mod 10;
    r := (r + 100) div 10 - 10;
    inc(i);
  end;
  c.cnt := i;
end;

function cmp(var a, b: TDecimal): integer;
var
  i, j: integer;
begin
  j := a.cnt;
  if b.cnt > j then
    j := b.cnt;
  for i := j - 1 downto 0 do begin
    if a.d[i] > b.d[i] then begin
      cmp := 1;
      exit;
    end else if a.d[i] < b.d[i] then begin
      cmp := -1;
      exit;
    end;
  end;
  cmp := 0;
end;

procedure println(var d: TDecimal);
var
  i: integer;
begin
  for i := d.cnt - 1 downto 0 do
    write(d.d[i]);
  writeln;
end;

var
  k, m, n: longint;
  kd, md, cd, nd, td, ad: TDecimal;
  i, j: integer;
  found: boolean;

procedure process;
begin

  { Read }
  read(k, m);
  { Init p10 }
  parse(k, kd);
  parse(m, md);
  { Solve }
  parse(1, cd); { Will use "cd" as a counter of number less that k in lex order }
  found := false;
  for i := 1 to MAX_DIG do begin
    { t - properly shifted k }
    parse(0, td);
    td.cnt := i;
    for j := 0 to kd.cnt - 1 do
      td.d[j - kd.cnt + td.cnt] := kd.d[j];
    dec(td.d[i - 1]);
    { All i digit numbers smaller t are before k in lex order }
    add(cd, td, ad);
    if i < kd.cnt then begin
      { One more number }
      parse(1, td);
      add(ad, td, ad);
    end;
    if i >= kd.cnt then begin
      { We have enough digits }
      if cmp(cd, md) > 0 then begin
        { Counter is already too large -- no solution }
        found := false;
        break;
      end;
      if cmp(ad, md) >= 0 then begin
        { Solution is here with this number of digits }
        sub(md, cd, nd);
        nd.cnt := i;
        inc(nd.d[i - 1]);
        { Carefully check for k itself }
        if cmp(nd, kd) = 0 then begin
          { just Ok. n = k }
          found := true;
          break;
        end else if cmp(nd, kd) < 0 then begin
          { m is too small }
          { continue with more digits }
        end else begin
          { Ok. Larger than k }
          parse(1, td);
          sub(nd, td, nd);
          found := true;
          break;
        end;
      end;
    end;
    cd := ad;
  end;
  { Write }
  if found then
    println(nd)
  else
    writeln(0);
end;

var
   sotest, kkk : integer;

begin
    read( sotest);
    for kkk:=1 to sotest do process;
end.

Comments

Please read the guidelines before commenting.


There are no comments at the moment.