Hướng dẫn giải của Trật tự


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

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.

Bình luận

Hãy đọc nội quy trước khi bình luận.


Không có bình luận tại thời điểm này.