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.
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