You are on page 1of 161

T SCH TRI THC DUY TN

NGUYN XUN HUY

SNG TO
TRONG THUT TON
V
LP TRNH
vi ngn ng Pascal v C#
Tp 2

Tuyn cc bi ton Tin nng cao


cho hc sinh v sinh vin gii

MC LC .

Chng 1 Cc bi ton v on thng............................................................................................ 4


Bi 1.1 on ri 1 ........................................................................................................................... 4
Bi 1.2 on gi 1 .......................................................................................................................... 8
Bi 1.3 on gi 2 .........................................................................................................................11
Bi 1.4 on gi 3 .........................................................................................................................13
Bi 1.5 on bao nhau 1 ................................................................................................................16
Bi 1.6 on bao nhau 2 ..............................................................................................................19
Bi 1.7 Ph on 1 ........................................................................................................................21
Bi 1.8 Xanh tm vng 1 ...........................................................................................................24
Bi 1.9 Xanh tm vng 2 ..........................................................................................................27
Bi 1.10 Ph on 2 .....................................................................................................................30
Bi 1.11 on ri 2 ......................................................................................................................34
Bi 1.12 Ghp hnh ch nht .........................................................................................................35
Bi 1.13 Xanh ...........................................................................................................................37
Bi 1.14 Xp on .........................................................................................................................39
Bi 1.15 Cc hnh ch nht ..........................................................................................................41
Bi 1.16 Cc tam gic vung cn .................................................................................................46
Chng 2 Cc hm Next ................................................................................................................52
Bi 2.1 S st sau cng cao .......................................................................................................52
Bi 2.2 S st sau cng ch s ......................................................................................................54
Bi 2.3 Cc hon v ........................................................................................................................55
Bi 2.4 T hp ...............................................................................................................................58
Bi 2.5 S Kapreka ........................................................................................................................61
Bi 2.6 Kha vng..........................................................................................................................66
Bi 2.7 Tr tin ...............................................................................................................................69
Bi 2.8 Dy Farey ..........................................................................................................................72
Bi 2.9 Qy Mi .............................................................................................................................77
Bi 2.10 Tng on .......................................................................................................................79
Bi 2.11 on khng gim di nht ..............................................................................................82
Bi 2.12 on n iu di nht ....................................................................................................84
Bi 2.13 Ly tha 2, 3 v 5 ............................................................................................................87
Chng 3 Tr chi ...........................................................................................................................89
Bi 3.1. Bc si A ..........................................................................................................................90
Bi 3.2. Bc si B ..........................................................................................................................92
Bi 3.3. Bc si C ..........................................................................................................................94
Bi 3.4. Chia on ..........................................................................................................................97
Bi 3.5. Bc si D ..........................................................................................................................97
Bi 3.6. Bc si E ...........................................................................................................................99
Bi 3.7. Bc si F .........................................................................................................................100
Bi 3.8. Chia Hnh ch nht .........................................................................................................102
Bi 3.9. Bc si G ........................................................................................................................103
Bi 3.10. Chia Hnh hp ...............................................................................................................103

Bi 3.11. Tr chi NIM ................................................................................................................104


Bi 3.12. C bng .........................................................................................................................106
Bi 3.13. C y ...........................................................................................................................113
Bi 3.14. Bc si H ......................................................................................................................114
Chng 4 Cc thut ton sp t ................................................................................................115
4.1 C tam ti ...............................................................................................................................115
4.2 Li tam gic u ...................................................................................................................117
4.3 Dng biu din ca giai tha ..................................................................................................121
4.4 Xp si ...................................................................................................................................127
4.5 Dy cc hon v ......................................................................................................................130
4.6 B bi .....................................................................................................................................134
4.7 Thun th ................................................................................................................................141
4.8 Cc nh khoa hc ...................................................................................................................144
4.9 Chn chic ng h .................................................................................................................152
4.10 S duy nht ...........................................................................................................................159

C h ng 1
C c b i to n v on th ng

Bn cn ch c k bi. C nhng bi mi xem ta thy ta ta nh nhau nhng kt qu l khc


nhau. in hnh l nhng bi ti u ha, tc l nhng bi tm max hay min ca mt hm. Cc rng buc
ch khc nhau i cht nhng kh s th li khc xa nhau.

Bi 1.1 on ri 1
Cho N on thng vi cc im u ai v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi. Lit k s lng ti a K on thng khng giao nhau. Hai on thng [a,b] v [c,d]
c coi l khng giao nhau nu xp chng trn cng mt trc s, chng khng c im chung. iu kin
ny i hi: b < c hoc d < a.
DOAN.INP
8
2 3
4 5
10 12
13 15
1 9
2 5
6 8
7 15

DOAN.OUT
5
1
2
7
3
4

D liu vo: tp vn bn DOAN.INP


Dng u tin: s t nhin N, 1 < N 1000.
Dng th i trong N dng tip theo, mi dng cha hai
s nguyn ai bi cch nhau qua du cch, biu th im u v
im cui ca on th i, i = 1..N.
D liu ra: tp vn bn DOAN.OUT
Dng u tin: s t nhin K.
K dng tip theo, mi dng mt s t nhin v th hin
ch s ca cc on ri nhau tm c.
Th d bn cho bit ti a c 5 on ri nhau l 1, 2, 7,
3 v 4.

Thut ton
Phng php: tham.
1. Sp cc on tng theo u phi b.
2. Khi tr: Ly on 1, t r = b1 l u phi ca on ny
3. Vi mi on j := 2..N tip theo xt:
Nu u tri ca on j, aj > r th ly on j a vo kt qu
v chnh r l u phi ca on j, r := bj.
phc tp: c NlogN chi ph cho quick sort.

(*

Pascal

*)

(*===========================================
Doan roi 1: Liet ke toi da cac doan thang
khong giao nhau
===========================================*)
program DoanRoi1;
uses crt;
const mn = 1001; bl = #32 {Du cch}; nl = #13#10 {Xung dng};
fn = 'doan.inp'; gn = 'doan.out';
type { M t mt on }
KieuDoan = record
a,b: integer;
id: integer; { Ch s on }
end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n,m,r: integer; { n s lng on }
{ m s lng on c chn }
{ r u phi ang duyt
}
d: md1; { cc on d[1..n] }
f,g: text;
c: mi1; { mng cha kt qa }
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n);
for i := 1 to n do
begin
read(f,d[i].a,d[i].b); d[i].id := i;
end;
close(f);
end;
(*--------------------------------Sp tng cc on d[t..p] theo
u phi b.
---------------------------------*)
procedure Qsort(t,p: integer);
var i,j,m: integer;
x: KieuDoan;
begin
i := t; j := p; m := d[(i + j) div 2].b;
while (i <= j) do
begin
while (d[i].b < m) do i := i + 1;
while (m < d[j].b) do j := j - 1;
if (i <= j) then
begin
x := d[i]; d[i] := d[j]; d[j] := x;
i := i + 1; j := j - 1;
end;
end;
if (t < j) then Qsort(t,j);
if (i < p) then Qsort(i,p);
end;
procedure XuLi;
var i: integer;

begin
m := 1; c[m] := 1; { a on 1 vo kt qu }
r := d[m].b; { u phi ca on cui trong kt qu }
for i := 2 to n do
if (r < d[i].a) then
begin
m := m + 1; c[m] := i; r := d[i].b;
end;
end;
procedure Ghi;
var i: integer;
begin
assign(g,gn); rewrite(g); writeln(g,m);
for i := 1 to m do writeln(g,d[c[i]].id);
close(g);
end;
BEGIN
Doc; Qsort(1,n); XuLi; Ghi;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
* Doan Roi 1: Lit k ti a k on ri nhau *
===============================================*/
namespace SangTao2 {
class DoanRoi1 {
static public Doan[] d;
static int n; // s on
static int m; // s on c chn cho kt qu
static int[] c; // lu kt qu
const string fn = "doan.inp";
const string gn = "doan.out";
static void Main(string[] args) {
Doc(); QSortB(d,0,n-1);
XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini "); Console.ReadLine();
}
static public void Doc() {
StreamReader f = File.OpenText(fn);
string s = f.ReadToEnd(); f.Close();
String[] ss = s.Split(
new char[] { ' ', '\n', '\r', '\t' },
StringSplitOptions.RemoveEmptyEntries);
int[] a = Array.ConvertAll(ss,
new Converter<string, int>(int.Parse));
n = a[0]; // so doan
d = new Doan[n];
int j = 1;
for (int i = 0; i < n; ++i, j += 2) // c on i
d[i] = new Doan(a[j], a[j + 1], i + 1);
} // Doc
static public void XuLi() {
m = 0;

c = new int[n];
c[m++] = 0; // chn on 0
int r = d[0].b; // thit lp gii hn phi
for (int i = 1; i < n; ++i)
if (r < d[i].a) { c[m++] = i; r = d[i].b; }
} // XuLi
// Sp tng cc on d[t..p] theo u phi b
static public void QSortB(Doan[] d, int t, int p) {
int i = t, j = p, m = d[(i + j) / 2].b;
while (i <= j) {
while (d[i].b < m) ++i;
while (d[j].b > m) --j;
if (i <= j) {
Doan x = d[i]; d[i] = d[j]; d[j] = x;
++i; --j;
}
}
if (t < j) QSortB(d, t, j);
if (i < p) QSortB(d, i, p);
}
static public void Ghi() {
StreamWriter g = File.CreateText(gn);
g.WriteLine(m);
for (int i = 0; i < m; ++i) g.WriteLine(d[c[i]].id);
g.Close();
}
// Hin th li cc files input, output kim tra
static public void XemKetQua() {
Console.WriteLine("\n Input " + fn);
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output " + gn);
Console.WriteLine(File.ReadAllText(gn));
}
}// DoanRoi1
public struct Doan { // M t mt on
public int a, b, id;
public Doan(int x1,int x2,int z) // To on mi
{ a = x1; b = x2; id = z; }
} // Doan
} // SangTao2

Gii thch chng trnh C#


1. Khai bo file text f, m file tn fn = doan.inp c ton b d liu vo bin string
s ri ng file li.
StreamReader f = File.OpenText(fn);
string s = f.ReadToEnd(); f.Close();
2. Tch string s thnh mng cc string ss[i] theo cc du ngn cch khai bo trong new
char [], loi b cc string rng.
Trong mt dng vn bn thng cha cc du ngn cch sau y (gi l cc du trng)
' ' - du cch
'\n' - du ht dng (du xung dng)
'\r' - du v u dng (du ENTER/RETURN)
'\t' - du tab

string[] ss = s.Split(new char [] { ' ', '\n', '\r', '\t' },


StringSplitOptions.RemoveEmptyEntries);
3. Chuyn i mi string ss[i] thnh s nguyn v ghi trong mng nguyn a
int[] a = Array.ConvertAll(ss,
new Converter<string, int>(int.Parse));
Sau bc 3 d liu trong file doan.inp c c vo mng a[0..n-1].
4. Ly s lng on : n = a[0];
5. Xin cp pht n con tr kiu Doan : d = new Doan[n];
6. Cp pht v khi tr cho mi on i = 0..n-1. on i c ch s l i+1:
int j = 1;
for (int i = 0; i < n; ++i, j += 2) // doc doan i
{ d[i] = new Doan(a[j], a[j + 1], i + 1); }
C nhiu phng thc c/ghi cc text file. Bn cn la chn v ghi nh mt phng thc m bn cm
thy tin li nht.
7. Bn c th t chc d liu Doan theo dng struct (bn ghi) hoc dng class (lp). im
khc nhau cn bn gia hai cu trc ny l, theo qui c ngm nh struct c truyn theo tr (by
val) cn class c truyn theo ch dn (by ref).
public struct Doan {
public int a, b; // dim u v im cui on
public int id;
// ch s on
// phng thc to on
public Doan(int x1, int x2, int z)
{ a = x1; b = x2; id = z; }
}

Bi 1.2 on gi 1
Cho N on thng trn trc s vi cc im u a i v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi. Hy tm s lng ti a K on thng gi nhau lin tip. Hai on thng [a,b] v

[c,d] c gi l gi nhau nu xp chng trn cng mt trc s th im u on ny trng vi im cui


ca on kia, tc l c = b hoc d = a.
DOAN.INP

DOAN.OUT

D liu vo: tp vn bn DOAN.INP: xem on gi 1


D liu ra: tp vn bn DOAN.OUT

5
2
1
7
3
4

3
7
3
9
4
5

cha duy nht mt s t nhin K.


Th d ny cho bit c ti a 3 on gi nhau lin tip l
[1,3], [3,4] v [4,5].

Thut ton
Phng php: Quy hoch ng + Tham.
Gi s cc on c sp tng theo u phi b. K hiu c(i) l s lng ti a cc on thng gi
nhau to thnh mt dy nhn on i lm phn t cui dy (khi kho st cc on t 1..i). Ta c
c(1) =1,
Vi i = 2...N: c(i) = max { c(j) | 1 j < i, on j k trc on i: bj = ai } + 1.

Li dng cc on sp tng theo u phi b, vi mi on i ta ch cn duyt ngc cc on j ng


trc on i cho n khi pht hin bt ng thc bj < ai.
Kt qu: K = max { c(i) | i = 1...n }.

phc tp: c N2 v vi mi on ta phi duyt ti a tt c cc on ng trc on .

(* Pascal *)
(*============================
on Gi 1: S lng ti a
cc on gi nhau.
============================*)
program DoanGoi1;
uses crt;
const
mn = 1001; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
type
KieuDoan = record a,b: integer; end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n,m: integer; { n s lng on, m s on c chn }
d: md1; { cc on d[1..n]}
f,g: text;
c: mi1; { c[i] = s lng max cc on gi nhau n i }
procedure Doc; t vit
procedure Qsort(t,p: integer);t vit
procedure XuLi;
var i,j: integer;
begin
c[1] := 1;
for i := 2 to n do { Tnh c[i] }
begin
c[i] := 0;
for j := i-1 downto 1 do
begin
if (d[j].b < d[i].a) { doan j khong noi voi i }
then break;
if (d[j].b = d[i].a) then { j noi voi i }
if (c[j] > c[i]) then c[i] := c[j];
end;
c[i] := c[i] + 1;
end;
end;
procedure Ket; { Tim c max va hien thi ket qua }
var i,imax: integer;
begin
assign(g,gn); rewrite(g);
imax := 1;
for i := 2 to n do
if (c[imax] < c[i]) then imax := i;
writeln(g,c[imax]); close(g);
end;
BEGIN
Doc; Qsort(1,n); XuLi; Ket;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
on Gi 1: S lng ti a cc on gi nhau
===============================================*/
namespace SangTao2 {
class DoanGoi1 {
static public Doan[] d; // cc on d[0..n-1]
static int n; // s on
static int m;// s max cc on gi nhau
const string fn = "doan.inp"; // input file
const string gn = "doan.out"; // output file
static void Main(string[] args) {
Doc(); QSortB(d,0,n-1);
XuLi(); Ghi();
XemKetQua(); Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void Doc(): t vit
// Sp tng cc on d[t..p] theo u phi b
static public void QSortB(Doan[]d,int t,int p): t vit
static public void XuLi() {
int[] c = new int[n];
// c[i] s lng max on gi ktthc ti on i
c[0] = 1; // ly on 0
int imax = 0;
for (int i = 1; i < n; ++i) {
c[i] = 0;
int jmax = i;
for (int j = i - 1; j >= 0; --j) {
if (d[j].b < d[i].a) break;
if (d[j].b == d[i].a)
if (c[j] > c[jmax]) jmax = j;
}
c[i] = c[jmax] + 1;
if (c[i] > c[imax]) imax = i;
}
m = c[imax];
}
static public void Ghi(){
StreamWriter g = File.CreateText(gn);
g.WriteLine(m); g.Close();
}
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
}// DoanGoi1
public struct Doan
{
public int a,b;
public Doan(int x1, int x2) { a = x1; b = x2; }
} // Doan
} // SangTao2

Ch thch

10

Trong bi ny ta khng cn s dng trng ch s ring id cho kiu on.


Trong phng n C# ta tranh th tm gi tr cmax = c[imax] sau mi ln tnh c[i].

Bi 1.3 on gi 2
Cho N on thng trn trc s vi cc im u a i v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi. Lit k ti a K on thng gi nhau lin tip.


DOAN.INP

DOAN.OUT

D liu vo: tp vn bn DOAN.INP: xem on gi 1


D liu ra: tp vn bn DOAN.OUT

5
2
1
7
3
4

7
3
9
4
5

3
2
4
5

Dng u tin: s t nhin K.


Tip n l K dng, mi dng cha mt s t nhin biu
th ch s ca on thng gi nhau lin tip trong dy tm c.
Th d ny cho bit ti a c 3 on 2, 4 v 5 to thnh
dy on gi nhau lin tip.

Thut ton
Tng t nh bi on gi 1 nhng cn to thm con tr trc. t[i] = j c ngha l on i
c gi sau on j. Th tc GiaiTrinh(i) lit k cc on gi lin tip t phi qua tri thc cht l
lit k theo chiu ngc cc phn t trong mng con tr trc t bt u t phn t th i. Gi s t c dng
sau,
t[2] = 0; t[4] = 2; t[5] = 4;
v gi s i = 5 l v tr t tr cmax, ta phi ghi vo file kt qu g dy cc on gi nhau lin tip
nh sau,
2 4 5
Ta ch vic gi quy mun nh sau
procedure GiaiTrinh(i: integer);
begin
if (i <> 0) then
begin GiaiTrinh(t[i]); writeln(g,d[i].id); end;
end;

0 01 2 3 4 5
0

2 4

phc tp: c N2.

(*

Pascal

*)

(*=============================================
Doan Goi 2: Liet ke toi da cac doan thang
goi nhau lin tiep
=============================================*)
program DoanGoi2;
uses crt;
const
mn = 1001; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
type
KieuDoan = record a,b,id: integer; end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n,m: integer; { n - so luong doan, m - so doan duoc chon }
d: md1; // cac doan

11

f,g: text;
c: mi1; { c[i] = so luong max doan goi voi doan i }
t: mi1; { tro truoc }
procedure Doc: t vit
procedure Qsort(i1,i2: integer): t vit
procedure XuLi;
var i,j,jmax: integer;
begin
fillchar(t,sizeof(t),0); {Khi tr mng tr trc}
c[1] := 1;
for i := 2 to n do
begin
c[i] := 0; jmax := i;
for j := i-1 downto 1 do
begin
if (d[j].b < d[i].a) then break;
if (d[j].b = d[i].a) then
if (c[j] > c[jmax]) then jmax := j;
end;
c[i] := c[jmax]+1; t[i] := jmax;
end;
end;
procedure GiaiTrinh(i: integer): t vit;
procedure Ket;
var i,imax: integer;
begin
assign(g,gn);rewrite(g);
imax := 1;
for i := 2 to n do
if (c[imax] < c[i]) then imax := i;
writeln(g,c[imax]);
GiaiTrinh(imax);
close(g);
end;
BEGIN
Doc; Qsort(1,n); XuLi; Ket;
END.

//

C#

using System;
using System.IO;
using System.Collections;
/*===============================================
* Doan Goi 2: Liet ke toi da cac doan goi nhau *
===============================================*/
namespace SangTao2 {
class DoanGoi2 {
static public Doan[] d;
static int n; // tong so doan
static int[] t; // tro truoc
const string fn = "doan.inp";
const string gn = "doan.out";
static void Main(string[] args){
Doc(); QSortB(d,0,n-1);
int m = 0; // so doan tim duoc
int imax = 0; // chi so doan cuoi trong day max

12

XuLi(ref imax, ref m); Ghi(imax,m);


XemKetQua(); Console.ReadLine();
}
static public void Doc(): t vit
static public void XuLi(ref int imax, ref int m) {
int [] c = new int[n];
t = new int[n];
Array.Clear(t, 0, t.Length);
t[0] = -1;
// c[i] - so luong doan goi ket thuc tai doan i
c[0] = 1; // lay doan 0
imax = 0;
for (int i = 1; i < n; ++i){
c[i] = 0;
int jmax = i;
for (int j = i - 1; j >= 0; --j){
if (d[j].b < d[i].a) break;
if (d[j].b == d[i].a)
if (c[j] > c[jmax]) jmax = j;
}
c[i] = c[jmax] + 1; t[i] = jmax;
if (c[i] > c[imax]) imax = i;
}
m = c[imax];
}
// Sap tang cac doan theo dau phai (b)
static public void QSortB(Doan[] d,int i1,int i2): t vit
static void Path(StreamWriter g, int imax) {
if (imax != -1)
{ Path(g,t[imax]); g.WriteLine(d[imax].id); }
}
static public void Ghi(int imax, int m){
StreamWriter g = File.CreateText(gn);
g.WriteLine(m); Path(g, imax); g.Close();
}
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
} // DoanGoi2
public struct Doan: t vit
} // SangTao2

Bi 1.4 on gi 3
Cho N on thng trn trc s vi cc im u a i v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi. i = 1..n. Lit k cc on thng gi nhau c tng chiu di C ln nht.

DOAN.INP

DOAN.OUT

D liu vo: tp vn bn DOAN.INP: xem bi on gi 1.

13

8
2
1
7
3
3
2
5
9

7
3
9
40
5
3
9
16

39
2
4

D liu ra: tp vn bn DOAN.OUT


Dng u tin: s t nhin C.
Mi dng tip theo cha mt s t nhin biu th ch s ca
on thng gi nhau lin tip trong dy tm c.
Th d ny cho bit hai on 2 v 4 to thnh dy on gi
nhau lin tip c tng chiu di max l 39.

Thut ton
Phng php: Quy hoch ng kt hp vi con tr trc t gii trnh kt qu.
Gi s cc on c sp tng theo u phi b. K hiu c(i) l tng chiu di ln nht cc on
thng gi nhau lin tip to thnh mt dy nhn on i lm phn t cui dy (khi kho st cc on t 1..i).
rng (bi ai) l chiu di on th i, ta c
c(1) = chiu di on 1 = b1 a1,
Vi i = 2..N: c(i) = max { c(j) | 1 j < i, on j k trc on i: bj = ai } + (bi ai),
Nu j l ch s t max th t ti = j.

phc tp: N2.

(*

Pascal

*)

(*=============================================
Doan Goi 3: Liet ke cac doan goi nhau
co tong chieu dai max
============================================*)
program DoanGoi3;
uses crt;
const
mn = 1001; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
type
KieuDoan = record a,b,id: integer; end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n,m: integer; { n s lng on, m s on c chn }
d: md1;
f,g: text;
c: mi1; {c[i] = chieu dai max nhan i lam doan cuoi}
t: mi1; { tro truoc }
procedure Doc; t vit
procedure Qsort(l,r: integer); t vit
procedure XuLi;
var i,j,jmax: integer;
begin
fillchar(t,sizeof(t),0);{ Kh to mng tr trc }
c[1] := d[1].b - d[1].a; { Chieu dai doan 1 }
for i := 2 to n do
begin
c[i] := 0; jmax := i;
for j := i-1 downto 1 do
begin
if (d[j].b < d[i].a) then break;

14

if (d[j].b = d[i].a) then


if (c[j] > c[jmax]) then
jmax := j;
end;
c[i] := c[jmax] + (d[i].b - d[i].a); t[i] := jmax;
end;
end;
procedure GiaiTrinh(i: integer); t vit
procedure Ket; t vit
BEGIN
Doc; Qsort(1,n); XuLi; Ket;
END.

//

C#

using System;
using System.IO;
using System.Collections;
/*================================================
* Doan Goi 3: Liet ke toi da cac doan goi nhau *
*
co tong chieu dai max
*
================================================*/
namespace SangTao2 {
class DoanGoi3 {
static public Doan[] d;
static int n; // tong so doan
static int[] t; // tro truoc
const string fn = "doan.inp";
const string gn = "doan.out";
static void Main(string[] args) {
Doc(); QSortB(d,0,n-1);
int maxlen = 0; // so doan tim duoc
int imax = 0; // chi so doan cuoi trong day max
XuLi(ref imax, ref maxlen);
Ghi(imax,maxlen);
XemKetQua(); Console.ReadLine();
}
static public void Doc(): t vit
static public void XuLi(ref int imax, ref int maxlen){
int [] c = new int[n];
t = new int[n];
Array.Clear(t, 0, t.Length);
t[0] = -1;
// c[i] - so luong doan goi ket thuc tai doan i
c[0] = d[0].b-d[0].a; // lay doan 0
imax = 0;
for (int i = 1; i < n; ++i) {
c[i] = 0;
int jmax = i; // Day dai nhat noi voi doan i
for (int j = i - 1; j >= 0; --j) {
if (d[j].b < d[i].a) break;
if (d[j].b == d[i].a)
if (c[j] > c[jmax]) jmax = j;
}
c[i] = c[jmax] + (d[i].b - d[i].a) ; t[i] = jmax;
if (c[i] > c[imax]) imax = i;
}

15

} //

maxlen = c[imax];
}
// Sap tang cac doan theo dau phai (b)
static public void QSortB(Doan[] d, int t, int p): t vit
static void Path(StreamWriter g, int imax): t vit
static public void Ghi(int imax, int maxlen): t vit
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
}// DoanGoi3
public struct Doan: t vit
SangTao2

Bi 1.5 on bao nhau 1


Cho N on thng trn trc s vi cc im u a i v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi, i = 1..n. Tm K l s lng nhiu on nht to thnh mt dy cc on bao nhau lin
tip. Hai on [a,b] v [c,d] c gi l bao nhau nu on ny nm lt trong an kia, tc l a c < d
b hoc c a < b d.
DOAN.INP

DOAN.OUT
D liu vo: tp vn bn DOAN.INP: xem bi trc

6
-1 12
8 10
8 11
2 7
17 18
13 20

D liu ra: tp vn bn DOAN.OUT


cha duy nht mt s t nhin K.
Th d ny cho bit ti a c 3 on bao nhau l cc
on [-1,12] [8,11] [8,10].

Thut ton
Phng php: Quy hoch ng.
Gi s cc on c sp tng theo u phi b nh sau. Nu hai on c cng u phi th on no
c u tri nh hn s c t sau. K hiu c(i) l s lng ln nht cc on bao nhau lin tip trong
on i. Ta c,
c(1) = 1,
Vi i = 2...N: c(i) = max { c(j) | 1 j < i, on j lt trong on i: aj ai } + 1,
phc tp: N2.
Hm SanhDoan(x,y) thit lp trt t gia hai on x v y nh sau:

(*

Nu x.b < y.b cho kt qu 1, nu khng: xt tip

Nu x.b > y.b cho kt qu 1, nu khng: xt tip

Xt trng hp x.b = y.b.


o

Nu x.a < y.a cho kt qu 1, nu khng: xt tip

Nu x.a > y.a cho kt qu 1, nu khng: xt tip

Hai on trng nhau: x.a = y.a v x.b = y.b cho kt qa 0.

Pascal

*)

uses crt;
const MN = 1001; bl = #32; nl = #13#10;

16

fn = 'doan.inp'; gn = 'doan.out';
type
Doan = record a,b: integer; end;
MD1 = array[0..MN] of Doan;
MI1 = array[0..MN] of integer;
var f,g: text;
d: MD1; { cac doan }
n: integer; { so doan }
procedure Doc; t lm
function SanhDoan(x,y: Doan): integer;
begin
if (x.b < y.b) then begin SanhDoan := -1; exit end;
if (x.b > y.b) then begin SanhDoan := 1; exit end;
if (x.a < y.a) then begin SanhDoan := 1; exit end;
if (x.a > y.a) then begin SanhDoan := -1; exit end;
SanhDoan := 0;
end;
procedure QSortB(t,p: integer);
var i,j: integer; m,x: Doan;
begin
i := t; j := p; m := d[(i+j) div 2];
while (i <= j) do
begin
while (SanhDoan(d[i],m) < 0) do i := i+1;
while (SanhDoan(d[j],m) > 0) do j := j-1;
if (i <= j) then
begin
x := d[i]; d[i] := d[j]; d[j] := x;
i := i+1; j := j-1;
end;
end;
if (t < j) then QSortB(t,j);
if (i < p) then QSortB(i,p);
end;
function XuLi: integer;
var c: mi1; { c[i] so doan bao nhau max }
i,j,cmax: integer;
begin
cmax := 0;
for i := 1 to n do
begin
c[i] := 0;
for j := i-1 downto 1 do
begin
if (d[j].b <= d[i].a) then break;
if (d[j].a >= d[i].a) then
if (c[j] > c[i]) then c[i] := c[j];
end;
c[i] := c[i] + 1;
if (cmax < c[i]) then cmax := c[i];
end;
XuLi := cmax;
end;
procedure Ghi(k: integer);
begin
assign(g,gn); rewrite(g); writeln(g,k); close(g);
end;

17

BEGIN
Doc; QSortB(1,n); Ghi(XuLi); readln;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
Doan Bao 1: So luong toi da cac doan
bao nhau
===============================================*/
namespace SangTao2 {
class DoanBao1 {
static public Doan[] d; // cac doan
static int n; // tong so doan
const string fn = "doan.inp";
const string gn = "doan.out";
static void Main(string[] args){
Doc(); QSortB(d, 0, n - 1);
Ghi(XuLi());
XemKetQua(); Console.WriteLine("\n Fini");
Console.ReadLine();
}
static public void Doc(): t vit
static public int XuLi(){
int [] c = new int [n];
int cmax = 0;
for (int i = 0; i < n; ++i){
c[i] = 0;
for (int j = i-1; j >= 0; --j){
if (d[j].b <= d[i].a) break;
if (d[j].a >= d[i].a)
if (c[j] > c[i]) c[i] = c[j];
}
++c[i];
if (cmax < c[i]) cmax = c[i];
}
return cmax;
} // XuLi
static public int SanhDoan(Doan x, Doan y){
if (x.b > y.b) return 1;
if (x.b < y.b) return -1;
// x.b == y.b
if (x.a < y.a) return 1;
if (x.a > y.a) return -1;
return 0;
}
// Sap tang cac doan theo dau b
// Hai doan cung dau b: doan nao a nho dat sau
static public void QSortB(Doan[] d, int t, int p){
int i = t, j = p;
Doan m = new Doan(d[(i + j) / 2]);
while (i <= j){
while (SanhDoan(d[i],m) < 0) ++i;
while (SanhDoan(d[j],m) > 0) --j;

18

if (i <= j){
Doan x = d[i]; d[i] = d[j]; d[j] = x;
++i; --j;
}
}
if (t < j) QSortB(d, t, j);
if (i < p) QSortB(d, i, p);
}
static public void Ghi(int m){
File.WriteAllText(gn, m.ToString());
}
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
}// DoanBao1
public struct Doan: t vit
} // SangTao2

Bi 1.6 on bao nhau 2


Cho N on thng trn trc s vi cc im u ai v im cui bi l nhng s nguyn trong khong

1000..1000, ai < bi, i = 1..n. Lit k ti a K on bao nhau.


DOAN.INP

DOAN.OUT
D liu vo: tp vn bn DOAN.INP: xem bi trc

6
-1 12
8 10
17 18
2 7
8 11
13 20

3
1
5
2

D liu ra: tp vn bn DOAN.OUT


Dng u tin: s t nhin K.
Tip n l K dng, mi dng cha mt s t nhin l
ch s ca on trong dy tm c. Cc ch s c li k
theo trt t bao nhau t ln n nh.
Th d ny cho bit ti a c 3 on bao nhau l cc
on 1, 5 v 2: [-1,12] [8,11] [8,10].

Thut ton
Ging bi on bao nhau 1. c danh sch on bao nhau ta dng mng tr t[1..n], t[i] tr n
on j l on nm trong on i v c[j] t gi tr max.
phc tp: N2.

(*

Pascal

*)

uses crt;
const MN = 1001; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
type
Doan = record a,b: integer; id: integer; end;
MD1 = array[0..MN] of Doan;
MI1 = array[0..MN] of integer;
var f,g: text;
d: MD1;
t: MI1; { tro truoc }
n: integer;
imax, k: integer;
procedure Doc; t lm
function SanhDoan(x,y: Doan): integer; t lm

19

procedure QSortB(t,p: integer): t lm


procedure XuLi;
var c: mi1;
i,j: integer;
begin
imax := 1;
for i := 1 to n do
begin
c[i] := 0; t[i] := 0;
for j := i-1 downto 1 do
begin
if (d[j].b <= d[i].a) then break;
if (d[j].a >= d[i].a) then
if (c[j] > c[i]) then
begin c[i] := c[j]; t[i] := j end;
end;
c[i] := c[i] + 1;
if (c[imax] < c[i]) then imax := i;
end;
k := c[imax];
end;
procedure Path(i: integer);
begin
if (i = 0) then exit;
writeln(g,d[i].id); Path(t[i]);
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g); writeln(g,k);
path(imax); close(g);
end;
BEGIN
Doc; QSortB(1,n); XuLi; Ghi; readln;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
Doan Bao 2: Liet ke toi da cac doan
bao nhau
===============================================*/
namespace SangTao2 {
class DoanBao2 {
static public Doan[] d; // Cac doan
static public int [] t; // Con tro truoc
static int n; // tong so doan
const string fn = "doan.inp";
const string gn = "doan.out";
static void Main(string[] args){
Doc(); QSortB(d, 0, n - 1);
int k, imax;
XuLi(out k, out imax); Ghi(k, imax);
XemKetQua(); Console.WriteLine("\n Fini");
Console.ReadLine();

20

}
static public void Doc(): t lm
static public void XuLi(out int cmax, out int imax){
int [] c = new int [n];
t = new int[n];
imax = 0;
for (int i = 0; i < n; ++i){
c[i] = 0; t[i] = -1;
for (int j = i-1; j >= 0; --j){
if (d[j].b <= d[i].a) break;
if (d[j].a >= d[i].a)
if (c[j] > c[i])
{
c[i] = c[j]; t[i] = j; }
}
++c[i];
if (c[imax] < c[i]) imax = i;
}
cmax = c[imax];
} // XuLi
static public int SanhDoan(Doan x, Doan y): t lm
static public void QSortB(Doan[] d, int t, int p): t lm
static void Path(StreamWriter g, int imax){
if (imax != -1)
{ g.WriteLine(d[imax].id); Path(g, t[imax]); }
}
static public void Ghi(int k, int imax){
StreamWriter g = File.CreateText(gn);
g.WriteLine(k); Path(g, imax); g.Close();
}
static public void XemKetQua(): xem bi trc
}// DoanBao2
public struct Doan: t lm
} // SangTao2

Bi 1.7 Ph on 1
Cho N on thng trn trc s vi cc im u a i v im cui bi l nhng s nguyn trong khong
1000..1000, ai < bi. Hy ch ra t nht K on thng sao cho khi t chng trn trc s th c th ph kn
on [x, y] vi ta nguyn cho trc.
DOAN.INP

DOAN.OUT

D liu vo: tp vn bn DOAN.INP: xem bi trc


D liu ra: tp vn bn DOAN.OUT

5
3 23
1 15
3 10
8 20
17 25
2 7

3
1
3
4

Dng u tin: s K, nu v nghim K = 0.


Tip theo l K s t nhin biu th ch s ca cc on
thng ph kn on [x, y].
Th d ny cho bit t nht l 3 on 1, 3 v 4 s ph kn
on [3, 23].

Thut ton
Phng php: Tham

21

Sp cc on tng theo u phi b.


k : = 1; { ch s u tin }
v := x; { u tri ca on [x,y] }
Lp n khi v y
Duyt ngc t N n k
Tm on j [aj, bj] u tin c u tri aj v;
Nu khng tm c: v nghim;
Nu tm c:
Ghi nhn on j;
t li v := bj;
t li k := j+1;

phc tp: N2.

(*

Pascal

*)

(*========================================
Phu doan 1
Tm t nht K on c th ph kn
on [x,y] cho trc
=========================================*)
program PhuDoan1;
uses crt;
const
mn = 2002; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
type
KieuDoan = record
a,b: integer;
id: integer; { Ch s on }
end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n: integer; { n - so luong doan }
d: md1; { cac doan }
f,g: text;
t: mi1;
x, y: integer; { Doan can phu }
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n);
readln(f,x, y);
for i := 1 to n do
begin
readln(f,d[i].a,d[i].b);
d[i].id := i;
end;
close(f);
end;
procedure Qsort(l,r: integer): t vit
(*---------------------------------------Duyet nguoc cac doan d[s..e]
tim doan i dau tien thoa d[i].a <= x
---------------------------------------*)

22

function Tim(s,e,x: integer): integer;


var i: integer;
begin
Tim := 0;
for i := e downto s do
if (d[i].a <= x) then
begin
Tim := i;
exit;
end;
end;
procedure Ket(k: integer): t vit
procedure XuLi;
var i,j,k,v: integer; { k - so doan tim duoc }
begin
v := x;
k := 0; t[k] := 0;
repeat
j := Tim(t[k]+1,n,v);
if (j = 0) then { Khong tim duoc }
begin Ket(0); { vo nghiem } exit; end;
v := d[j].b; k := k + 1; t[k] := j;
until (v >= y);
Ket(k); { co nghiem }
end;
BEGIN
doc; qsort(1,n); xuli;
END.

//

C#

using System;
using System.IO;
using System.Collections;
/*===============================================
* Phu Doan 1: Liet ke toi thieu cac doan
*
*
phu doan [x,y] cho truoc
*
===============================================*/
namespace SangTao2 {
class PhuDoan1 {
static public Doan[] d; // cac doan
static int n; // tong so doan
static int m;// so doan tim duoc
static int[] c; // luu ket qua cac doan duoc chon
const string fn = "doan.inp";
const string gn = "doan.out";
static int x, y; // doan [x,y] can phu
static void Main(string[] args) {
Doc(); QSortB(d, 0, n - 1);
m = XuLi(); Ghi();
XemKetQua(); Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void Doc() {
int[] a = Array.ConvertAll(File.ReadAllText(fn).
Split(new chae[] {' ','\n','\r','\t'},

23

StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0;
n = a[j++]; // tong so doan
d = new Doan[n];
// Doc doan xy can phu
x = a[j++]; y = a[j++];
for (int i = 0; i < n; ++i, j += 2) // doc doan i
d[i] = new Doan(a[j], a[j + 1], i + 1);
} // Doc
static public int XuLi() {
c = new int [n];
int v = x; // dau trai doan [x,y]
int k = 0; // dem so doan tim duoc
int left = 0; // can trai
do {
int j = Tim(left, n - 1, v);
if (j == -1) return 0; // vo nghiem
c[k++] = j; // Tim duoc
left = j + 1;
v = d[j].b; // Chinh lai dau trai
} while (v < y);
return k;
} // XuLi
// Duyet nguoc cac doan d[s..e]
// tim doan dau tien i: d[k].a <= x
static public int Tim(int s, int e, int x) {
for (int i = e; i >= s; --i)
if (d[i].a <= x) return i;
return -1;
}
// Sap tang cac doan theo dau phai (b)
static public void QSortB(Doan[] d, int t, int p): t vit
static public void Ghi() : t vit
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
}// PhuDoan1
public struct Doan: t vit
} // SangTao2

Bi 1.8 Xanh tm vng 1


Cho 4 loi on thng sn cc mu xanh, , tm v vng, bao gm x on mu xanh mi on di
dx, d on mu mi on di dd, t on mu tm mi on di dt v v on mu vng mi on di dv.
Cc on thng cng mu th c cng chiu di. Hy chn mi loi mt s on thng ri xp ni nhau
theo chu vi thu c mt hnh ch nht c din tch ln nht vi cc cnh ln lt mang cc mu tnh
theo chiu quay ca kim ng h l xanh, , tm, vng. Cc i lng trong bi u l cc s nguyn
dng.
XDTV1.INP

XDTV1.OUT

15 12
6 21

15120
15 4 12 3

xanh
v

24

14 15
10 28

n
g

tm

D liu vo: tp vn bn XDTV1.INP gm 4 dng, mi dng hai s nguyn dng vit cch nhau
Dng th nht: x dx
Dng th hai: d dd
Dng th ba: t dt
Dng th t: v dv
D liu ra: tp vn bn XDTV1.OUT
Dng u tin: Din tch ca hnh ch nht xanh - - tm - vng.
Dng th hai: 4 s cho bit s lng on thng cn chn theo mi loi mu ghp c hnh ch
nht din tch max.
Kt qu trn cho bit cn chn 15 on xanh, 4 on , 12 on tm v 3 on vng ghp thnh
hnh ch nht xanh tm vng vi din tch max l 15120 = (15*12)*(4*21) = (12*15)*(3*28).

Thut ton
Phng php: Tham.
Ta gi mt b xanh - tm l mt cp (nx,nt) trong nx l s t nht cc on mu xanh t lin tip
nhau trn ng thng to thnh on AB v nt l s t nht cc on mu tm t lin tip nhau trn ng
thng to thnh on CD sao cho AB = CD. Ta c ngay nx*dx = nt*dt. D dng tm c nx =
Bcnn(dx,dt)/dx v nt = Bcnn(dx,dt)/dt, trong Bcnn(a,b) l hm tnh bi chung nh nht ca hai s t
nhin a v b. Tng t ta tnh cho b - vng. Tip n ta tnh xem ti a c th ly c bao nhiu b
xanh - tm v b - vng. D thy S b xanh - tm = min(x div nx, t div nt). Tng t ta tnh cho b vng.

phc tp: O(1).

(*

Pascal

*)

(******************************************
Xanh Do Tim Vang 1
******************************************)
program xdtv1;
uses crt;
const
fn = 'xdtv1.inp'; gn = 'xdtv1.out'; bl = #32;
var
n: longint;
f,g: text;
x,d,t,v: longint; { so doan X D T V }
dx,dd,dt,dv: longint; { cheu dai moi doan }
nx,nt,nd,nv: longint; { so doan X D T V can chon }
procedure Doc;
begin
assign(f,fn); reset(f);
readln(f,x,dx); readln(f,d,dd); readln(f,t,dt); readln(f,v,dv);
close(f);
end;
function Ucln(a,b: longint): longint;
var r: longint;

25

begin
while (b <> 0) do
begin r := a mod b; a := b; b := r; end;
Ucln := a;
end;
(*-----------------------------------Bcnn(a,b) = (a * b)/Ucln(a,b)
-------------------------------------*)
function Bcnn(a,b: longint): longint;
begin Bcnn := a * (b div Ucln(a,b)); end;
function Min(a,b: longint): longint; t vit
procedure XuLi;
var b, nxt, ndv: longint;
begin
b := Bcnn(dx,dt);
nx := b div dx; { so doan xanh trong 1 bo xanh tim }
nt := b div dt; { so doan tim trong 1 bo xanh tim }
nxt := Min(x div nx, t div nt); { so bo xanh tim }
nx := nxt * nx; { so doan xanh can chon }
nt := nxt * nt; { so doan tim can chon }
b := Bcnn(dd,dv);
nd := b div dd; { so doan do trong 1 bo do vang }
nv := b div dv; { so doan vang trong 1 bo do vang }
ndv := Min(d div nd, v div nv);{ so bo do vang }
nd := ndv * nd; { so doan do can chon }
nv := ndv * nv; { so doan vang can chon }
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g);
writeln(g,nx*dx*nd*dd);{ dien tich }
writeln(g,nx,bl,nd,bl,nt,bl,nv); { so doan moi loai }
close(g);
end;
BEGIN
Doc; XuLi; Ghi;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
Xanh Do Tim Vang 1
===============================================*/
namespace SangTao2 {
class Xdtv1 {
static int x, dx, d, dd, t, dt, v, dv;
static int nx, nd, nt, nv; // Dap so
const string fn = "xdtv1.inp";
const string gn = "xdtv1.out";
static void Main(string[] args) {
Doc(); XuLi(); Ghi();
XemKetQua(); Console.WriteLine("\n Fini");
Console.ReadLine();
}

26

static public void Doc(){


int[] a = Array.ConvertAll(File.ReadAllText(fn).
Split(new chae[] {' ','\n','\r','\t'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0;
x = a[j++]; dx = a[j++]; d = a[j++]; dd = a[j++];
t = a[j++]; dt = a[j++]; v = a[j++]; dv = a[j];
} // Doc
static public void XuLi(){
int b = Bcnn(dx,dt);
nx = b / dx; // so doan xanh trong 1 bo xanh tim
nt = b / dt; // so doan tim trong 1 bo xanh tim
int nxt = Min(x / nx, t / nt); // so bo xanh tim
nx = nxt * nx; // so doan xanh can chon
nt = nxt * nt; // so doan tim can chon
b = Bcnn(dd,dv);
nd = b / dd; // so doan do trong 1 bo do vang
nv = b / dv; // so doan vang trong 1 bo do vang
int ndv = Min(d / nd, v / nv);// so bo do vang
nd = ndv * nd; // so doan do can chon
nv = ndv * nv; // so doan vang can chon
} // XuLi
static public int Ucln(int a, int b){
int r;
while (b != 0) { r = a % b; a = b; b = r; }
return a;
}
static public int Bcnn(int a, int b)
{ return a*(b/Ucln(a, b));}
static public int Min(int a,int b): t vit
static public void Ghi(){
StreamWriter g = File.CreateText(gn);
g.WriteLine((nx*dx*nd*dd)); // dien tich
g.WriteLine(nx+" "+nd+" "+nt+" "+nv);//so doan moi loai
g.Close();
}
// Hien thi lai cac files input, output
static public void XemKetQua(): t vit
}// Xdtv1
} // SangTao2

Bi 1.9 Xanh tm vng 2


Cho 4 loi on thng sn cc mu xanh di dx, di dd, tm di dt v vng di dv. Cc on
thng cng mu th c cng chiu di v s lng khng hn ch. Hy chn ra khng qu N on thng ri
xp ni nhau theo chu vi thu c mt hnh ch nht c din tch ln nht vi cc cnh ln lt mang
cc mu theo chiu quay ca kim ng h l xanh, , tm, vng. D liu trong bi u l cc s nguyn
dng.
XDTV2.INP

XDTV2.OUT

D liu vo: tp vn bn XDTV2.INP

27

35
3 2 2 5

480
8 10 12 4

Dng th nht: s N > 0.


Dng th hai: bn s dx dd dt dv
D liu ra: tp vn bn XDTV2.OUT
Dng u tin: Din tch ca hnh ch nht xanh - tm - vng.
Dng th hai: 4 s cho bit s lng on thng cn
chn theo mi loi mu ghp c hnh ch nht din
tch max.

Kt qu trn cho bit cn chn 8 on xanh, 10 on , 12 on tm v 4 on vng ghp thnh


hnh ch nht c din tch max l 480.

Thut ton
Phng php: Tham.
Tng t nh bi Xanh tm vng 1, trc ht ta tnh cc b xanh - tm (nx,nt) v b - vng (nd, nv).
Tip n ta tnh xem khi ly i b xanh tm kt hp vi j b - vng th thu c hnh ch nht c
din tch max l bao nhiu. Lu rng i b xanh - tm s gm i(nx+nt) on thng. S on thng cn li
khi s l N i(nx+nt). S ny s to ra c j = (N i(nx+nt)) / (nd+nv) b - vng.

phc tp: O(n).

(*

Pascal

*)

(******************************************
Xanh Do Tim Vang 2
******************************************)
program xdtv2;
uses crt;
const
fn = 'xdtv2.inp'; gn = 'xdtv2.out'; bl = #32;
var
n: longint;
f,g: text;
x,d,t,v: longint;
dx,dd,dt,dv: longint;
nx,nt,nd,nv: longint;
smax,bmax: longint;
procedure Doc: T vit;
function Ucln(a,b: longint): T vit;
function Bcnn(a,b: longint): T vit;
function Min(a,b: longint): T vit;
(*--------------------------------------------------------1 bo xanh - tim = (sx,st) = (so doan xanh, so doan tim)
sx = bcnn(dx,dt) div dx
st = bcnn(dx,dt) div dt
bxt = sx + st
--------------------------------------------------------*)
procedure XuLi;
var b: longint;
bxt, bdv: longint;
s: longint;
sx,st, sd, sv: longint;
begin
b := bcnn(dx,dt);

28

sx := b div dx;
st := b div dt;
bxt := sx + st;
b := Bcnn(dd,dv);
sd := b div dd;
sv := b div dv;
bdv := sd + sv;
smax := 0; bmax := 0;
for b := 1 to ((n - bdv) div bxt) do
begin
s := (b*sx*dx)*(((n b*bxt) div bdv)*sd*dd);
if (s > smax) then
begin bmax := b; smax := s; end;
end;
nx := bmax * sx; nt := bmax * st;
b := smax div (nx*dx); { Chieu dai canh Do ( = Vang) }
nd := b div dd; nv := b div dv;
end;
procedure Ghi: T vit;
BEGIN
Doc; XuLi; Ghi;
END.

// C#
using System;
using System.IO;
using System.Collections;
/*===============================================
Xanh Do Tim Vang 2
===============================================*/
namespace SangTao2 {
class Xdtv2 {
static int n;
static int dx, dd, dt, dv;
static int nx, nd, nt, nv; // Dap so: so luong moi loai
const string fn = "xdtv1.inp";
const string gn = "xdtv1.out";
static void Main(string[] args){
Doc(); XuLi(); Ghi();
XemKetQua(); Console.WriteLine("\n Fini");
Console.ReadLine();
}
static public void Doc(){
int[] a = Array.ConvertAll(File.ReadAllText(fn).
Split(new chae[] {' ','\n','\r','\t'},
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0;
n = a[j++]; dx = a[j++]; dd = a[j++];
dt = a[j++]; dv = a[j];
} // Doc
static public void XuLi() {
int b = Bcnn(dx,dt);
int sx = b / dx; // so luong doan xanh trg 1 bo XT
int st = b / dt; // so lg doan tim trg 1 bo X-T
int sxt = sx+st; // tg so doan xanh va tim trg bo XT

29

b =
int
int
int
int
int
for

Bcnn(dd,dv);
sd = b / dd, sv = b / dv; // do, vang
sdv = sd + sv;// tg so doan do va vg trg bo DV
smax = 0; // dt max
bxtmax = 0; // so bo XT toi da
bb = (n-sdv)/sxt; // can tren cua cac bo XT
(b = 1; b <= bb; ++b) { // b - so bo XT
int s = (b*sx*dx)*(((n-b*sxt)/sdv)*sd*dd);// dt
if (s > smax) { bxtmax = b; smax = s; }

}
nx = bxtmax * sx; nt = bxtmax * st;
b = smax / (nx * dx); // chieu dai canh Do = Vang
nd = b/dd; nv = b/dv;
} // XuLi
static public int Ucln(int a, int b): T vit;
static public int Bcnn(int a, int b): T vit;
static public int Min(int a,int b): T vit;
static public void Ghi(): T vit;
static public void XemKetQua(): T vit;
}// Xdtv2
} // SangTao2

Bi 1.10 Ph on 2
Cho n on thng <ai , bi> vi cc im u ai v im cui bi l nhng s nguyn trong khong
1000..1000,
ai < bi v thuc mt trong 4 dng sau y:
[d,c] - on ng: cha im u d v im cui c,
(d,c] - on m tri: khng cha im u d, cha im cui c,
[d,c) - on m phi: cha im u d, khng cha im cui c,
(d,c) - on m: khng cha im u d v im cui c.
Hy ch ra t nht K on thng sao cho khi t chng trn trc s th c th ph kn on <x, y>
vi ta nguyn cho trc.
DOAN.INP
6
(4,10 )
(-2, 5)
[ 5 , 7] [6, 7)
[7, 8) (8,9)
(7 , 10 ]

DOAN.OUT
3
1
2
6

D liu vo: tp vn bn DOAN.INP


Dng u tin: s t nhin 1 < N 1000.
Dng th hai: on x y
T dng th ba lit k cc on, mi dng
c th cha nhiu on, mi on c ghi trn
trn mt dng.
D liu ra: tp vn bn DOAN.OUT
Dng u tin: s K, nu v nghim K=0.
Tip theo l K s t nhin biu th ch s ca
cc on thng ph kn on x y.

Kt qu trn cho bit t nht l 3 on 1, 2 v 6 s ph kn on (4,10).


Ch : Gia cc s v cc k t trong file input c th cha cc du cch.

Thut ton
Phng php: Tham

30

ng dng thut ton ca bi Ph on 1 ta a cc on v cng mt dng ng bng cch chnh


li cc u m. C th l thm/bt im u m ca mi on mt lng = 0.3 nh sau,
[d,c] gi nguyn
(d,c] [d + , c],
[d,c) [d, c - ],
(d,c) [d + , c - ].
Qui tc trn kh d hiu. Bn hy gii thch v sao chn = 0.3 m khng chn = 0.5?
Hai trng a v b th hin cc im u v cui mi on cn c khai bo kiu real (float).
Cc bin lin quan n cc trng ny trong th tc x l cng cn c khai bo theo cc kiu trn.
Ta c tt c cc on v ghi vo mng d[0..N], trong d[0] s cha on x, y.
Cch c cc on c t chc trn c s gi thit l cc on c vit ng c php. Mi ln ta
c mt k t ch t tp input. Nu (ch = () hoc (ch = [) th ta gp k t u on: ta tin hnh c mt
on. c mt on ta ln lt c s th nht, b qua du phy (,) ngn cch gia hai s ri c s
th hai. Th tc c mt on kt thc khi gp mt trong hai du ng ngoc l ] hoc ). Cn c vo cc
du m v ng ngoc u v cui mi on ta xc nh lng cn thm hoc bt cho mi im u
hoc cui on, ng nhin cc im ny cn c biu din di dng s thc.

phc tp: N2.

Ch
Bn c th dng k thut ng dng chuyn trc s sang trc s "phng i" gp 3 ln. Khi cc
on tng ng s c chuyn nh sau:
[d,c]
(d,c]
[d,c)
(d,c)

[3d
[3d
[3d
[3d

+
+

1,
1,
1,
1,

3c
3c
3c
3c

+
+
-

1],
1],
1],
1].

Tc l gi li kiu nguyn v chn = 1. Cch lm ny c n gin hn trong trng hp gii hn ca d v


c l nh.

(*

Pascal

*)

(*========================================
Phu doan 2
=========================================*)
program PhuDoan2;
uses crt;
const
mn = 2002; bl = #32; nl = #13#10;
fn = 'doan.inp'; gn = 'doan.out';
MoVuong = '['; DongVuong = ']'; MoTron = '('; DongTron = ')';
NgoacMo = [MoVuong, MoTron]; NgoacDong = [DongVuong, DongTron];
ChuSo = ['0'..'9']; CongTru = ['+','-']; eps = 0.3;
type
KieuDoan = record
a,b: real;
id: integer; { ch s on }
end;
md1 = array[0..mn] of KieuDoan;
mi1 = array[0..mn] of integer;
var n: integer; { n - so luong doan }
d: md1;
f,g: text;
t: mi1;
xy: KieuDoan;

31

ch: char;
k: integer; {dem so doan da doc}
Ngoac: char;
(* Doc 1 so nguyen tu input file *)
function DocSo: integer;
var s,dau: integer;
begin
s := 0; dau := 1;
while not (ch in (CongTru + ChuSo)) do read(f,ch);
if (ch in CongTru) then
begin
if (ch = '-') then dau := -1;
read(f,ch);
end;
while not (ch in ChuSo) do read(f,ch);
repeat
s := 10*s + ord(ch) - ord('0');
read(f,ch);
until not (ch in ChuSo);
DocSo := dau * s;
end;
procedure DocDoan;
begin
k := k + 1; d[k].id := k; Ngoac := ch; d[k].a := DocSo;
if (Ngoac = MoTron) then d[k].a := d[k].a + eps;
while (ch <> ',') do read(f,ch);
d[k].b := DocSo;
while not(ch in NgoacDong) do read(f,ch);
if (ch = DongTron) then d[k].b := d[k].b - eps;
end;
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n); k := -1;
while (k < n) and (not eof(f)) do
begin
read(f,ch);
if (ch in NgoacMo) then DocDoan;
end;
close(f); xy.a := d[0].a; xy.b := d[0].b;
end;
procedure Qsort(l,r: integer): xem bi ph on 1;
function Tim(id,ic: integer; x: real): xem bi ph on 1;
procedure Ket(k: integer): xem bi ph on 1;
procedure XuLi: xem bi ph on 1;
BEGIN
Doc; Qsort(1,n); XuLi;
END.

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class PhuDoan2 { // Cac doan dong mo
static public string fn = "Doan.inp";

32

static public string gn = "Doan.out";


static public string s; // du lieu vao
static public Doan[] d; // cac doan
static public int[] c; // luu cac doan ket qua
static public Doan xy;
static public int n = 0; // so luong doan
static public int si; // index cho s
static int m; // so luong doan phu
const float eps = 0.3f;
static void Main(string[] args) {
Doc(); QSortB(d, 0, n - 1);
m = XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XemKetQua(): t lm
static public void Doc() {
s = (File.ReadAllText(fn)).Trim();
si = 0; n = DocSo();
xy = DocDoan(0);
d = new Doan[n];
for (int i = 0; i < n; ++i)
d[i] = DocDoan(i+1);
}
static public void Ghi(): t lm
static public int XuLi(): t lm
static public int Tim(int i, int j, float x): t lm
static public void QSortB(Doan[] d, int t, int p): t lm
// c on th i
static public Doan DocDoan(int i) {
Cach();
char mo = s[si++];
float a = DocSo();
if (mo == '(') a += eps;
float b = DocSo();
Cach();
char dong = s[si++];
if (dong == ')' b -= eps;
return new Doan(a, b, i);
}
// b qua cc du trng
static public void Cach() {
while (s[si]==' '||s[si]=='\n'
||s[si]=='\t'||s[si]=='\r') ++si;
}
static public void DenSo() {
while ((s[si]<'0'||s[si]>'9')&&(s[si]!='+')
&&(s[si]!='-')) ++si;
}
static public int DocSo(){
int m = 0, dau = 1;
DenSo();
if (s[si] == '+') ++si;
if (s[si] == '-') { ++si; dau = -1; }
do {
m = m * 10 + s[si++] - '0';
} while (s[si] >= '0' && s[si] <= '9');
return dau*m;

33

}
} // PhuDoan2
public struct Doan { // M t mt on
public float a, b;
public id;
public Doan(float x1, float x2, int z)
{ a = x1; b = x2; id = z; }
} // Doan
} // SangTao2

// To on mi

Bi 1.11 on ri 2
Cho N on thng vi cc im u ai v im cui bi l nhng s nguyn trong
khong1000..1000, ai < bi. Lit k s lng ti a cc on thng ri nhau. Hai on c xem l ri
nhau nu chng khng c im chung. Cc on c dng nh trong bi Ph on 2.
DOAN.INP

DOAN.OUT

8
5
( -2, 3) [3 , 5) 1 2 7 3 4
[8, 12] [13 ,15 )
(1 , 9 ) ( 2, 5 ]
[5 ,8 ) [7, 15]

D liu vo: tp vn bn DOAN.INP


Dng u tin: s t nhin N > 1.
T dng th hai: lit k cc on, mi dng
c th cha nhiu on, mi on c ghi trn
trn mt dng.
D liu ra: tp vn bn DOAN.OUT
Dng u tin: s K.
Tip theo l K s t nhin biu th ch s ca
cc on thng ri nhau.

Kt qu trn cho bit c ti a 5 on ri nhau l 1, 2, 7, 3 v 4.

Thut ton
Phng php: Tham.
Trc ht ta chnh li cc u h ging nh bi trc sau p dng thut ton ca bi on ri.
Cc im u v cui on v cc bin lin quan c khai bo kiu s thc.

phc tp: N.logN chi ph cho quick sort.

(*

Pascal

*)

(*========================================
liet ke toi da cac doan thang roi nhau
=========================================*)
program DoanRoi2;
uses crt;
T chc d liu: xem bi Ph on 2
function DocSo: xem bai Phu doan 2;
procedure DocDoan: xem bai Phu doan 2;
procedure Doc: xem bai Phu doan 2;
procedure Qsort(l,r: integer): xem bai Phu doan 2;
procedure XuLi : xem bai Doan roi 1;
procedure Ket: xem bai Doan roi 1 ;
BEGIN
Doc;
Qsort(1,n);
XuLi; Ket;
END.

34

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class DoanRoi2 { // Cac doan dong mo
T chc d liu: xem bi Ph on 2
static void Main(string[] args) {
Doc(); QSortB(d, 0, n - 1);
XuLi(); Ghi();
XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XemKetQua(): xem bai Phu doan 2
static public void Doc(): xem bai Phu doan 2
static public void Ghi(): xem bai Doan Roi 1
static public void XuLi(): xem bai Doan roi 1
// Sap tang cac doan theo dau phai (b)
static public void QSortB(Doan[] d, int t, int p): t lm
static public Doan DocDoan(int i): xem bai Phu doan 2
static public int DocSo(): xem bai Phu doan 2
} // DoanRoi2
public struct Doan: xem bai Phu doan 2
} // SangTao2

Bi 1.12 Ghp hnh ch nht


Cho N on thng cng chiu di d n v. Hy chn K on ghp thnh cnh ca hnh ch nht
c din tch ln nht.
Input: Hai s N v d, n 4.
Output: Hin th trn mn hnh
- t: Tng s on cn chn t,
- a: S on t trn 1 chiu rng
- b: S on t trn 1 chiu di,
- s: Din tch max.
Th d,
Input: N = 23, d = 2.
Output:
22
5
6
120.

Thut ton
nh l Trong cc hnh ch nht cng chu vi th hnh vung c din tch ln nht.
Chng minh
Gi c l chu vi ca hnh ch nht, a l chiu rng, b l chiu di, b a, d l lch gia chiu di b
v chiu rng a. Ta c, b = a + d v c = 2(a+a+d) = 4a + 2d, din tch s = a(a+d). Thay gi tr a = (c2d)/4
vo biu thc tnh din tch v rt gn ta thu c s = c 2/16 d2/4 = (c2 4d2)/16. Gi tr s t max khi v
ch khi d = 0, tc l khi a = b. Vy hnh ch nht c din tch ln nht l c2/16 chnh l hnh vung.
T nh l trn ta rt ra heuristics sau y: mun xy dng mt hnh ch nht c din tch ln nht
t mt chu vi c c nh vi cc cnh nguyn cho trc ta phi chn lch gia chiu di v chiu rng
nh nht c th c.
Khi tr: a = b = N div 4.

35

Xt cc trng hp s on cn tha r = N mod 4.


r = 0: b qua
r = 1: b qua
r = 2: thm chiu di 1 on, b := b + 1;
r = 3: thm chiu di 1 on, b := b + 1;
Tng qut: a = N div 4; b = a + (N mod 4) div 2;
Khi din tch s l: s = a*b*d*d.
Th d, N = 23, d = 2: a = 23 div 4 = 5; b = a + (N mod 4) div 2 = 5 + (3 div 2) = 5 + 1 = 6;
t = 2*(a+b) = 2*(5+6) = 22; s = a*b*d*d = 5*6*2*2 = 120.

phc tp: O(1).

(* Pascal *)
(*========================================
Chon t trong n doan de ghep duoc HCN
dien tich max
=======================================*)
program GhepChuNhat;
uses crt;
const bl = #32;
procedure ChuNhatMax(n,d: longint);
var a,b,t,s: longint;
begin
a := n div 4; b := a + ((n mod 4) div 2);
t := 2 * (a + b); { tong so doan }
s := a * b * d * d;
writeln(t,bl,a,bl,b,bl,s);
end;
BEGIN
ChuNhatMax(23,2);
END.
Kt qu d kin:
22 5 6 120

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class GhepHCN {
static void Main(string[] args){
ChuNhatMax(23,2);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void ChuNhatMax(int n, int d){
int a = n / 4;
int b = a + ((n % 4) / 2);
int t = 2 * (a + b);
int s = a * b * d * d;
Console.WriteLine(t + " " + a + " " + b + " " + s);
}
} // GhepHCN
} // SangTao2

36

Bi 1.13 Xanh
Cho x on thng mu xanh c chiu di bng nhau l dx n v v d on mu c chiu di
bng nhau l dd n v. Hy chn nx on xanh v nd on t trn chu vi ca hnh ch nht to thnh
mt ng vin an mu (cc mu xen k nhau) v din tch ca hnh l ln nht.
Input: Bn s x, dx, d v dd, x 2, d 2.
Output: Hin th trn mn hnh
- nx: S on xanh c chn,
- nd: S on c chn,
- s: Din tch max.
* Th d 1
input: (x, dx, d, dd) = (5, 2, 7,
output: (nx, nd, s) = (5, 5, 24)
* Th d 2
input: (x, dx, d, dd) = (6, 2, 7,
output: (nx, nd, s) = (6, 6, 56)
* Th d 3
input: (x, dx, d, dd) = (6, 2, 7,
output: (nx, nd, s) = (6, 6, 36)
* Th d 4
input: (x, dx, d, dd) = (7, 2, 7,
output: (nx, nd, s) = (6, 6, 56)

2)

3)

Hnh ch nht
c cnh an mu
xanh - v t
din tch max

2)

3)

x = 11, dx = 1,
d = 10, dd = 2.
nx = 10, nd = 10,
s = 7 8 =

56.

Thut ton
D thy l thu c hnh c ng vin an mu th cn chn s on xanh nx v s on nd
nh nhau, tc l chn nx = nd = min(x, d). Khi chu vi ca hnh s gm t = nx + nd = 2nx = 2nd on, v
do t l mt s chn. Do t chn nn (t mod 4) s bng 0 hoc 2.
K hiu a l s on (tnh c xanh v ) cn t trn mt chiu rng, b l s on (tnh c xanh v
) cn t trn mt chiu di ca hnh. Xt hai trng hp dx = dd v dx dd.
1. Trng hp th nht: dx = dd. Ta c, a = b = t div 4. Nu (t mod 4 = 2). Ta thm vo chu vi mt
cp xanh na. Vy ta cn chn:
- nx = min(x,d) on xanh,
- nd = nx on ,
- Din tch max: s = a * b * dx * dx vi
a = t div 4 l s on t trn 1 chiu rng,
b = a + ((t mod 4) div 2) l s on t trn 1 chiu di.
2. Trng hp th hai: dx dd. Ta thy, m bo tnh an mu th a v b phi c cng tnh chn
l. T thy rng khi (t mod 4 = 2) ta phi b qua s d, v nu thm cho chiu di b 1 on na th tnh
chn l ca a v b s khc nhau. rng khi a v b cng chn th hnh nhn c s vung v mi cnh
cha ng z = a div 2 on xanh v z on . Khi din tch c th tnh theo cng thc: s = sqr(z * (dx +
dd)). Nu a v b cng l th s lng on xanh v s lng on trong mt cnh s hn km nhau 1
n v. Nu cnh ny nhiu xanh hn th cnh k vi cnh s nhiu hn xanh. Khi din tch s
c tnh theo cng thc
s = (z * dx + (z+1) *dd) * (z * dd + (z+1) * dx) = (z * dx + z * dd + dd) * (z * dd + z * dx + dx)
= (z * (dx + dd) + dd) * (z * (dx + dd) + dx) = (k + dd) * (k + dx)
vi z = a div 2, k = (a div 2)*(dx + dd).

37

Kt qu l cn chn:
nx = min(x,d). Chu vi 2*nx phi l bi ca 4, tc l nx phi chn. Nu nx l th t li nx := nx 1.
nd = nx;
tng cng t = nx + nd on, trong
S on t trn 1 chiu rng: a = t div 4,
S on t trn 1 chiu di: b = a,
Din tch max: (k+dd) * (k+dx), k = (a div 2)*(dx+dd).

phc tp: O(1).

(* Pascal *)
program XanhDo;
uses crt;
const bl = #32;
function Min(a,b: longint): t vit
procedure XD(x,dx,d,dd: longint);
var a,b,nx,nd,k,t,s: longint;
begin
if (dx = dd) then
begin
nx := Min(x,d); nd := nx; t := nx + nd;
a := t div 4;
b := a + ((t mod 4) div 2); s := a * b * dx * dx
end
else { dx <> dd }
begin
nx := Min(x,d);
if (nx mod 2 > 0) then nx := nx - 1;
nd := nx; t := nx + nd; a := t div 4; b := a;
k := (a div 2) * (dx + dd);
if (Odd(a)) then s := (k + dx) * (k + dd)
else s = k*k;
end;
writeln(nx,bl,nd,bl,s);
end;
BEGIN
XD(7, 2, 7, 3);
END.

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class XanhDo {
static void Main(string[] args){
XD(11, 1, 9, 2);
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XD(int x, int dx, int d, int dd){
int nx = Min(x,d); // so luong doan xanh can chon
int nd; // so luong doan do can chon
int t; // tong so: nx + nd
int a,b; // chieu rong, dai tinh theo so doan

38

int s; // dien tich max


if (dx == dd){
nd = nx; t = nx + nd;
a = t / 4; b = a+((t % 4)/2);
s = a*b*dx*dx;
} else {
if (nx % 2 > 0) --nx;
nd = nx; t = nx+nd; b = a = t / 4;
int k = (a/2)*(dx+dd);
s = (a % 2 == 0) ? k * k : (k+dx)*(k+dd);
}
Console.WriteLine("\n " + nx + " " + nd + " " + s);
}
static public int Min(int a,int b): t vit
} // XanhDo
} // SangTao2

Bi 1.14 Xp on
Cho N on thng trn trc s vi cc im u xi l nhng s nguyn trong khong 1000..1000
v di di l nhng s nguyn dng trong khong 1..1000, i = 1..N. Tnh tng chiu di cc on
ph trn trc s.
DOAN.INP
5
3 5
-11 3
-20 4
-12 8
2 5

OUTPUT
28

D liu vo: tp vn bn DOAN.INP


Dng u tin: s t nhin 1 < N 1000.
Dng th i trong N dng tip theo, mi dng cha hai
s nguyn ai di cch nhau qua du cch, biu th im u
v chiu di ca on th i, i = 1..N.
D liu ra: hin th trn mn hnh tng chiu di t cc
on ph trn trc s.

Thut ton
Phng php: tham.
Sp tng cc on theo im u x.
Ta dng k hiu [x,y] biu din cho on thng c im u x v im cui y, x:d biu din cho on
thng c im u x v chiu di d. Ta nh ngha mt ln l on to bi cc on giao nhau lin tip. Hai
on [a,b] v [c,d] c gi l giao nhau nu chng c im chung. iu kin ny c ngha im u ca
on ny nm trong on th hai, tc l a c b hoc c a d. Do cc on c sp tng theo im
u x nn hai on xi:di v xj:dj s giao nhau khi v ch khi xj xi + di. rng xi + di l im cui ca
oan i. Nu hai on i v j giao nhau th ta hp chng thnh mt on [a,b] vi a = xi v b = max(xi + di,
xj+dj). Kt hp cc on giao nhau lin tip n mc ti a ta thu c mt ln gi l ln ti i [a,b] c
chiu di b a.
Ta khi tr ln [a, b] bng on u tin x1:d1, c th l a := x1, b := x1+d1 (= a + d1).
Vi mi on i := 2..N ta xt:
- Nu on i giao vi ln [a,b], tc l xi b th ta hp on i vi ln to ra ln mi [a,b]
bng cch chnh b := max(b, xi + di) .
- Nu on i khng giao vi ln [a,b] th ta cng tch ly chiu di ca ln [a,b] hin c vo
bin tng t ri sinh ra ln mi t on i.
t := t + (b a);

39

a := xi ; b := a + di;
Sau khi kt thc duyt cc on ta cng nt ln cui cng vo tng t bng thao tc t := t + (b a).

phc tp: O(N.logN) chi ph cho sp xp Qsort.

(*

Pascal

*)

(**************************************
Xep doan
***************************************)
program XepDoan;
uses crt;
const
bl = #32; fn = 'DOAN.INP'; mn = 1001;
type KieuDoan = record x: integer; d: integer; end;
md1 = array[0..mn] of KieuDoan;
var c: md1; { chua cac doan }
n: integer;
f: text;
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n);
for i := 1 to n do readln(f,c[i].x,c[i].d);
close(f);
end;
(*--------------------------------Sap tang cac doan theo
diem dau x
---------------------------------*)
procedure Qsort(t,p: integer): t vit;
function max(a,b: integer): t vit
function Tong: longint;
var t: longint; { tong do dai }
a, b: integer; { lan [a, b] }
i: integer;
begin
t := 0;
a := c[1].x; b := a + c[1].d; { Khoi tri lan }
for i := 2 to n do
if (c[i].x <= b) then b := max(b,c[i].x + c[i].d)
else
begin
t := t + (b - a);
a := c[i].x; b := a + c[i].d;
end;
Tong := t + (b - a);
end;
BEGIN
Doc; Qsort(1,n); writeln(Tong);
END.

//

C#

using System;
using System.IO;
using System.Collections;
namespace SangTao2 {

40

class XepDoan {
const string fn = "doan.inp";
const string gn = "doan.out";
static public int n; // so luong doan
static public Doan[] c; // cac doan
static void Main(string[] args) {
Doc(); QSort(0, n - 1);
Console.WriteLine("\n \n Dap so: "+CoverSum());
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void Doc(): t vit
static public int CoverSum() {
int a = c[0].x, b = a + c[0].d, t = 0;
for (int i = 1; i < n; ++i)
if (c[i].x <= b) b = Max(b, c[i].x + c[i].d);
else { t += (b-a); a = c[i].x; b = a+c[i].d; }
return t + (b - a);
}
static public int Max(int a, int b): t vit
// Sap cac doan tang theo diem dau x
static public void QSort(int s, int e): t vit
} // XepDoan
public struct Doan: t vit
} // SangTao2

Bi 1.15 Cc hnh ch nht


ACM
Trn mt phng ta cho N hnh ch nht (HCN) c din tch khc 0 v c cc cnh song song vi
cc trc ta . Mi HCN c m t bng b bn s nguyn (x1,y1) v (x2,y2) biu th ta nguyn ca
hai nh i din.
Yu cu: xc nh din tch phn mt phng b cc HCN ph.
HCN.INP
5
0
1
5
4
7

HCN.OUT
35

0
2
3
1
3

2
4
3
6
9

4
6
7
5
0

D liu vo: tp vn bn HCN.INP


Dng u tin: s t nhin 1 < N 1000.
Dng th i trong N dng tip theo, mi dng cha 4
s nguyn x1, y1, x2, y2 cch nhau qua du cch.
D liu ra: tp vn bn HCN.OUT cha tng n v
din tch trn mt phng b cc HCN ph.

Thut ton
Phng php: Tham.
y

41

1. c d liu v chnh li cc ta sao cho


x1 x2 v y1 y2. iu ny c ngha l ta qui c mi HCN
y
ABCD u c xc nh qua 2 nh i din D (nh Ty-Nam)
1
v B (nh ng-Bc): D(x1, y1), B(x2, y2).
Khi c d liu ta ng thi lc bt cc gi tr y trng
D
C
lp v sp cc gi tr y1 v y2 theo chiu tng ghi vo mt
x1
x2
mng y[1..m]. Nh vy, gi tr ln nht ca m l 2n. Ta gi phn
mt phng gii hn bi hai ng thng song song vi trc honh v ct trc tung ti im y[i] v y[i+1] l
bng i. Ta c m1 bng m s t 1 n m1. Bng u tin c m s 1 nm gia hai ng y[1] v y[2],
bng cui cng c m s m1 nm gia hai ng y[m1] v y[m]. Nhim v cn li l tnh din tch b
ph trn mi bng. Tng s din tch b ph ca cc bng s l p s cho bi ton.
2. Ta li sp cc HCN theo chiu tng ca ta x1.
3. Vi mi HCN h(x1, y1, x2, y2) ta xt cc bng i trong khong t y1 n y2. Vi bng i gi s ta
bit phn b cc HCN 1..(h1) ph trn bng ny. Ta k hiu s[i] v e[i] l gii hn honh tri v phi
ca phn ang b ph trn bng i. Din tch hin b ph trn bng i s l: (y[i+1]y[i])*(e[i] s[i]), trong
y[i+1] y[i] l chiu rng ca bng i. Ta cn chnh li phn b ph trong bng i khi xt thm HCN h(x1, y1,
x2, y2). D thy, nu x1 nm gia s[i] v e[i] th ta cn chnh li e[i] theo cng thc e[i] := max(e[i], x2).
Ngc li, nu x1 > e[i] th ta kt thc ln (s[i],e[i]) ny nh sau: Tnh din tch ln ny v a vo bin
tch ly din tch dt sau t li cn s[i] := x1; e[i] := x2.
Do cc honh y1 v y2 c sp tng nn ta c th gi th tc tm kim nh phn BnSearch
xc nh bng cha y1.

phc tp: Cc thut ton sp xp v chn i hi ti a N2, Th tc x l xt mi HCN 1 ln v


duyt 2n bng. Tng hp: N2.

(* Pascal *)
(**********************************************
Cac hinh chu nhat
*********************************************)
program HinhChuNhat;
uses crt;
const mn = 2001; fn = 'HCN.INP'; gn = 'HCN.OUT';
bl = #32; nl = #13#10;
type CN = record
x1, y1: integer;
x2, y2: integer;
end;
mcn1 = array[0..mn] of CN;
mi1 = array[0..mn] of integer;
var
n,m: integer; { n - so HCN, m - so lan }
h: mcn1; { cac HCN }
y: mi1; { ranh gioi cac lan }
s, e: mi1; { Cac diem dau va cuoi cua bang }
f,g: text;
dt: Longint;
function Max(a,b: integer): t vit
(*----------------------------Hon i tr a b
------------------------------*)
procedure Chinh(var a,b: integer);
var c: integer;
begin
if (a > b) then begin c := a; a := b; b := c;

end;

42

end;
(*-----------------------------------Tim nhi phan v trong y[1..m]
-------------------------------------*)
function BinSearch(v: integer): integer;
var d,c,t: integer;
begin
d := 1 ; c := m;
while (d < c) do
begin
t := (d + c) div 2;
if (y[t] < v) then d := t + 1
else c := t;
end;
BinSearch := d;
end;
(*----------------------------Xen them v vao day
da sap tang y[1..m]
------------------------------*)
procedure Insert(v: integer);
var d: integer;
begin
if (m = 0) then { danh sach rong }
begin m := m + 1; y[m] := v; exit; end;
d := BnSearch(v);
if (y[d] = v) then exit; { da co trong danh sach }
if (y[d] < v) then begin m := m + 1; y[m] := v; exit; end;
move(y[d], y[d+1],sizeof(integer)*(m-d+1));
y[d] := v; m := m + 1;
end;
(*------------------------------Doc du lieu va sap theo Y
luoc bot cac Y bang nhau
------------------------------*)
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n); m := 0;
for i := 1 to n do
begin
readln(f,h[i].x1,h[i].y1,h[i].x2,h[i].y2);
Chinh(h[i].x1, h[i].x2); Chinh(h[i].y1, h[i].y2);
insert(h[i].y1); insert(h[i].y2);
end;
close(f);
end;
procedure SortByX1(d,c: integer);
var i,j,m: integer;
v: CN;
begin
i := d; j := c;
m := h[(i+j) div 2].x1;
while (i <= j) do
begin
while (h[i].x1 < m) do i := i + 1;
while (m < h[j].x1) do j := j - 1;

43

if (i <= j) then
begin
v := h[i]; h[i] := h[j]; h[j] := v;
i := i + 1; j := j - 1;
end;
end;
if (d < j) then SortByX1(d,j);
if (i < c) then SortByX1(i,c);
end;
(*---------------------------------Xet HCN d, tinh tung phan
phu trong moi lan
------------------------------------*)
procedure Hinh(x1, x2, y1, y2: integer);
var i: integer;
begin
{ Tim xuat hien cua y1 trong cac lan }
i := BinSearch(y1);
while (y[i] < y2) do
begin
if (x1 <= e[i]) then
e[i] := Max(e[i], x2)
else
begin
dt := dt + (e[i] - s[i]) * (y[i+1] - y[i]);
s[i] := x1; e[i] := x2;
end;
i := i + 1;
end;
end;
procedure XuLi;
var d: integer;
begin
{ Khoi tri }
dt := 0;
for d := 1 to m-1 do
begin s[d] := -maxint; e[d] := s[d]; end;
{ Duyet cac HCN }
for d := 1 to n do
Hinh(h[d].x1, h[d].x2, h[d].y1, h[d].y2);
{ Tong hop ket qua }
for d := 1 to m-1 do
dt := dt + (e[d] - s[d]) * (y[d+1] - y[d]);
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g); writeln(g,dt); close(g)
end;
BEGIN
Doc; SortByX1(1,n); XuLi; Ghi;
END.

// C#
using System;
using System.IO;
using System.Collections;

44

namespace SangTao2 {
class Hcn {
const string fn = "hcn.inp";
const string gn = "hcn.out";
static public int n,m; // n - so luong HCN; m - so bang
static public HCN[] c;
static public int dt; // tong dien tich
static public int[] y;
static void Main(string[] args) {
Doc(); QSortByx1(0, n - 1);
XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void Ghi()
{ File.WriteAllText(gn,dt.ToString()); }
static public void XemKetQua(): t vit
static public void XuLi(){
dt = 0; // tong dien tich
int[] s = new int[m]; // diem dau cac bang
int [] e = new int [m]; // diem cuoi cac bang
for (int i = 0; i < m; ++i)
s[i] = e[i] = int.MinValue;
// Duyet cac HCN
for (int i = 0; i < n; ++i) {
// xu li HCN i
int sj = BinSearch(c[i].y1);
int ej = BinSearch(c[i].y2);
for (int j = sj; j < ej; ++j){
// xet bang j
if (c[i].x1 <= e[j]) e[j] = Max(e[j], c[i].x2);
else {
dt += (e[j] - s[j])*(y[j+1]-y[j]);
s[j] = c[i].x1; e[j] = c[i].x2;
}
}
}
// Tong hop ket qua
int m1 = m - 1;
for (int j = 0; j < m1; ++j)
dt += (e[j] - s[j])*(y[j+1]-y[j]);
}
static public int Max(int a, int b): t vit
static public void Doc() {
int[] v =
Array.ConvertAll(((File.ReadAllText(fn))).Split(
new chae[] { ' ', '\t', '\r', '\n' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0; n = v[j];
c = new HCN[n];
int dx, dy, bx, by, t;
m = 0;
y = new int[2*n];
for (int i = 0; i < n; ++i, j += 4) {
dx = v[j + 1]; dy = v[j + 2];
bx = v[j + 3]; by = v[j + 4];
if (dx > bx) { t = dx; dx = bx; bx = t; }
if (dy > by) { t = dy; dy = by; by = t; }

45

c[i] = new HCN(dx, dy, bx, by);


Insert(dy); Insert(by);
}
}
// Tim nhi phan gia tri v trong y[0..m-1]
static public int BinSearch(int v) {
int left = 0, right = m-1, midle;
while (left < right) {
midle = (left + right)/2;
if (y[midle] < v) left = midle + 1;
else right = midle;
}
return left;
}
// Xen toa do v vao danh sach cac lan y
static public void Insert(int v) {
if (m == 0) { y[m++] = v; return; }
int i = BinSearch(v);
if (y[i] == v) return;
if (y[i] < v) { y[m++] = v; return; }
Array.Copy(y, i, y, i + 1, m - i);
y[i] = v; ++m;
}
// Sap cac HCN tang theo x1
static public void QSortByx1(int s, int e) {
int i = s, j = e, m = c[(i + j) / 2].x1;
HCN t;
while (i <= j) {
while (c[i].x1 < m) ++i;
while (c[j].x1 > m) --j;
if (i <= j) {
t = c[i]; c[i] = c[j]; c[j] = t;
++i; --j;
}
}
if (s < j) QSortByx1(s, j);
if (i < e) QSortByx1(i, e);
}
} // Hcn
public struct HCN {
public int x1,y1,x2,y2;
public HCN(int dx, int dy, int bx, int by)
{ x1 = dx; y1 = dy; x2 = bx; y2 = by; }
}
} // SangTao2

Bi 1.16 Cc tam gic vung cn


ACM
Trn mt phng ta cho N tam gic vung cn, hai cnh gc vung song song vi hai trc ta
, cnh huyn nm bn phi tam gic. C th l nu k hiu tam gic l ABC th ta qui nh nh A l
nh gc vung, cnh gc vung AB song song vi trc honh ox, cnh gc vung AC song song vi trc
tung oy, AB = AC = d. Mi tam gic c m t bng b ba s nguyn x, y, d trong (x,y) l ta
nguyn ca nh A, d l chiu di cnh gc vung.

46
TAMGIAC.INP TAMGIAC.OUT

5
6
1
2
4
4

A
o

16.50
0
0
1
1
5

3
3
3
2
2

B
x

Yu cu: Tnh din tch do cc tam gic ph trn mt phng ta .


D liu vo: text file TAMGIAC.INP
Dng u tin: s t nhin N trong khong 2 .. 1000.
N dng tip theo: mi dng 3 s x y d cch nhau qua du cch, x v y bin thin trong khong
1000..1000, d trong khong 1..1000.
D liu ra: text file TAMGIAC.OUT cha mt s thc duy nht S l din tch b cc tam gic ph
trn mt phng ta .

Thut ton
Y

Tng t nh bi Cc Hnh ch nht. Vi mi tam gic (x,


y, d) ta to ra hai ng song song vi trc honh v ct trc tung
ti cc im y v y+d, c th l mt ng cha cnh y v mt
M
P
R
T
ng i qua nh ca tam gic. Cc ng thng ny s to ra cc
bng. Vi mi tam gic (TG) ta cng xt tng t nh HCN, ngha
Q
l xt cc bng cha trong TG . Bin din tch dt c khai bo
kiu float v cc hnh trong bng j s l hnh thang c y ln l
X E
S
V
e[j]s[j], y nh bng y ln h, h l chiu cao: h = y[j+1]y[j]
= rng ca bng. Khi chuyn t bng j ln bng j+1 ta phi
chnh li u phi x2 ca cnh y TG thnh x2 h v TG lc ny s ngn li. Khi tnh phn giao nhau ta
cn phi tr i din tch ca TG nm ngoi phn giao . Hnh v cho ta thy khi xt tam gic XYV v
bng gii hn trong 2 ng thng TM v SE, th ln (S, E) s c m rng thnh ln (S, V). Din tch
trc ca ln SE chnh l din tch hnh thang vung TMES, nay ln (S,V) c din tch ca hnh thang
vung TRVS. Nh vy ta tnh di ra phn din tch tam gic MPQ. D dng xc nh c din tch z
ca tam gic vung cn ny: t k = MP = PQ, ta c z = k2/2.Ta xc nh k nh sau. k = MP = TP TM =
SXTM = x(e[j]h), trong h l chiu rng ca bng j ang xt, h = y[j+1]y[j], e[j] l im cui ca
ln ang xt, x l honh ca nh gc vung trong tam gic XYV ang xt.

phc tp: N2.

(* Pascal *)
(**********************************************
Cac tam giac vuong can
*********************************************)
program TamGiacVuongCan;
uses crt;
const mn = 2001; bl = #32; nl = #13#10;

47

fn = 'TamGiac.inp'; gn = 'TamGiac.out';
type TG = record
x,y: integer;
d: integer;
end;
mtg1 = array[0..mn] of TG;
mi1 = array[0..mn] of integer;
mr1 = array[0..mn] of real;
var
n,m: integer; { n - so tam giac }
y: mi1;
{ m - so diem y, max(m) = 2n }
t: mtg1;
f,g: text;
dt: real; // tong dien tich
(*-------------------------------------------To chuc du lieu cho Bang i
s[i], e[i] - can trai va phai cua Bang
----------------------------------------------*)
s, e: mi1;
function Max(a,b: integer): t vit
(*----------------------------Xen them v vao day
da sap tang y[1..m]
------------------------------*)
procedure Insert(v: integer); t vit
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n);
m := 0;
for i := 1 to n do
begin
readln(f,t[i].x,t[i].y,t[i].d);
Insert(t[i].y); Insert(t[i].y + t[i].d);
end;
close(f);
end;
{ Sap cac TG tang theo x }
procedure SortByX(d,c: integer); t vit
{ Tim nhi phan v trong y[1..m] }
function BinSearch(v: integer): integer; t vit
(*--------------------------------------Xet hinh Tam giac h: tinh cac o
hinh h phu tren cac Bang
--------------------------------------*)
procedure Hinh(x1,y1,d: integer);
var i,y2,x2,h,k: integer;
begin
{ Tim xuat hien cua toa do y1 trong cac lan }
i := BinSearch(y1);
x2 := x1 + d; y2 := y1 + d;
while (y[i] < y2) do
begin
h := y[i + 1] - y[i];
if (x1 <= e[i]) then
begin
k := x1 - (e[i] - h); e[i] := Max(e[i], x2);

48

if (k > 0) then dt := dt - (real(k * k) / 2);


end
else
begin
if (e[i] > s[i]) then
dt := dt + h * (2 * (e[i] - s[i]) - h) / 2;
s[i] := x1; e[i] := x2;
end;
i := i + 1; x2 := x2 - h;
end;
end;
procedure XuLi;
var i, h: integer;
begin
for i := 1 to m do
begin s[i] := -maxint; e[i] := s[i]; end;
dt := 0.0;
{ Duyet cac TG }
for i := 1 to n do Hinh(t[i].x,t[i].y,t[i].d);
{ Tong hop ket qua }
for i := 1 to m-1 do
begin
h := y[i + 1] - y[i];
if (e[i] > s[i]) then
dt := dt + h * (2 * (e[i] - s[i]) - h) / 2;
end;
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g); writeln(g,dt:0:2); close(g)
end;
BEGIN
Doc; SortByX(1,n); XuLi; Ghi;
END.

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class TamGiac {
const string fn = "TamGiac.inp";
const string gn = "TamGiac.out";
static public int n, m; // n - so luong HCN; m - so bang
static public TG[] c;
static public float dt; // tong dien tich
static public int[] y;
static void Main(string[] args){
Doc(); QSortByx1(0, n - 1); XuLi();
Ghi(); XemKetQua();
Console.WriteLine("\n Fini "); Console.ReadLine();
}
static public void Ghi(): t vit
static public void XemKetQua(): t vit
static public void XuLi() {
dt = 0F;

49

int[] s = new int[m];


int[] e = new int[m];
for (int i = 0; i < m; ++i)
s[i] = e[i] = int.MinValue;
// Duyet cac TG c[i]
for (int i = 0; i < n; ++i) {
int x2 = c[i].x1+c[i].d; // dau phai cua canh day
int sj = BinSearch(c[i].y1);
int ej = BinSearch(c[i].y1 + c[i].d);
for (int j = sj; j < ej; ++j) {
// xet bang j
int h = y[j + 1] - y[j]; // do rong cua bang j
if (c[i].x1 <= e[j]) {
int k = c[i].x1 - (e[j] - h);
if (k > 0) dt -= (float)(k * k) / 2;
e[j] = Max(e[j], x2);
}
else {
if (e[j] > s[j])
dt += (float)(2*(e[j]-s[j])-h)*h/2;
s[j] = c[i].x1; e[j] = x2;
}
x2 -= h;
} // xong bang j
} // xong TG i
// Tong hop ket qua
int m1 = m - 1;
for (int j = 0; j < m1; ++j) {
int h = y[j+1]-y[j]; // do rong cua bang
if (e[j] > s[j])
dt += (float)(2*(e[j]-s[j])-h)* h/2;
}
static public int Max(int a, int b): t vit
static public void Doc() {
int[] v =
Array.ConvertAll(((File.ReadAllText(fn))).Split(
new char[] { ' ', '\t', '\r', '\n' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0; n = v[j];
c = new TG[n];
m = 0;
y = new int[2 * n];
for (int i = 0; i < n; ++i, j += 3) {
Insert(v[j + 2]); Insert(v[j + 2] + v[j + 3]);
c[i] = new TG(v[j + 1], v[j + 2], v[j + 3]);
}
}
// Tim nhi phan gia tri v trong y[0..m-1]
static public int BinSearch(int v): t vit
// Xen toa do v vao danh sach cac lan y
static public void Insert(int v): t vit
// Sap cac TG tang theo x1
static public void QSortByx1(int s, int e): t vit
} // TamGiac
public struct TG {
public int x1, y1, d;

50

public TG(int dx, int dy, int dd)


{ x1 = dx; y1 = dy; d = dd; }
}
} // SangTao2

51

C h ng 2
C c h m Ne xt

Trong hu ht cc bi ca Chng, khi trnh by tham bin kiu mng trong cc hm v th tc ta


gi thit l cc kiu ny c khai bo trc. Th d, kiu mng nguyn mt chiu c khai bo nh
sau:
(* Pascal *) type mi1 = array[0..MN] of integer;
trong MN l hng s ln cho kch thc mi bi ton, th d
const MN = 2000;
Trong C# mng c khai bo trc tip hoc thng qua class, th d,
int [] a = new int [2000];
Class Array { };
Ty theo bi ton v ngn ng lp trnh chn, ta c th hoc khng s dng phn t u tin v
cui cng ca mng. Nh vy, mng x gm n phn t s c k hiu l x[1..n] trong Pascal hoc x[0..n1]
trong C#. Trong Pascal khai bo tham bin kiu var (truyn theo bin hay a ch) cho mng th th tc s
c gi nhanh hn, trong C# cc mng c ngm nh l truyn theo bin / a ch.

Bi 2.1 S st sau cng cao


Chiu di ca mt s t nhin l s ch s ca s . cao ca mt s t nhin l tng cc ch s
ca s . Cho s t nhin x ghi trong h m b, c chiu di N. Tm s t nhin y st sau x c cng chiu
di, cng cao v cng h m vi x.
DOCAO.INP
10 5
2 3 9 9 0

D liu vo: tp vn bn DOCAO.INP

DOCAO.OUT
1
2 4 0 8 9

Dng u tin: hai s t nhin b v N cch nhau qua


du cch, 2 b 100, 2 N 1000.
Dng th hai: s x vi cc ch s ghi cch nhau qua
du cch.

D liu ra: tp vn bn DOCAO.OUT


Dng u tin: ghi 1 nu c nghim, 0: nu v nghim.
Dng th hai: s y vi cc ch s ghi cch nhau qua du cch.

Thut ton
cao ca s x s khng i nu ta ng thi tng v gim hai ch s ca x cng mt n v. Ta
duyt ln lt cc ch s ca x t phi qua tri, trc ht tm ch s xj > 0 u tin c th gim 1 n
v. Tip n ta duyt tip t j1 qua tri tm mt ch s xi < (b1) u tn sau j c th tng thm 1 n

52

v. Nu khng tm c xj hoc xi th x khng c s st sau. Nu tm c ng thi hai ch s xj v xi nh


trn th ta sa x nh sau:

Gim xj 1 n v,

Tng thm xi 1 n v,

Lt li on x[i+1..n].
Vi th d x[1..5] = (2,3,9,9,0) trong h m thp phn (b = 10) ta tm c j = 4, x[j] = 9, i = 2, x[i]
= 3. Sau khi gim x[4] v tng x[2] 1 n v ta thu c x[1..5] = (2,4,9,8,0). S ny cn ln, nu lt li
on x[3..5] s thu c x[1..5] = (2,4,0,8,9). y l s cn tm.
V sao li lm nh vy? Gii thch iu ny kh d nu rng x[j+1..n] cha ton 0 (ch s nh
nht trong h m b) v x[i+1..j1] cha ton (b1) (ch s ln nht trong h m b). T suy ra rng
on x[i+1..n] c sp tng. Lt li on ta s thu c dy cc ch s gim dn. V x[i] c thm
1 n v nn n ln hn s ban u. Khi lt li ta s thu c s st sau s ban u.
Hm Next di y bin i trc tip x[1..n] thu c s st sau. Ta s dng phn t x[0] = b
lm gii hn cho qu trnh duyt ngc. Phn t x[0] ny c gi l lnh canh. N c nhim v lm cho
vng lp dng mt cch t nhin m khng cn phi kim tra gii hn ch s ca mng (rang check).
phc tp: c N, do mi ch s ca x c thm v x l khng qu 2 ln.

(* Pascal *)
function Next(var x: mi1; n,b: integer): Boolean;
var i,j,t,b1: integer;
begin
Next := FALSE;
x[0] := b; j := n;
while (x[j] = 0) do j := j - 1;
if (j = 0) then exit; { ko co so sat sau }
i := j - 1; b1 := b - 1 ;
while (x[i] = b1) do i := i - 1;
if (i = 0) then exit; { Ko co so sat sau }
x[j] := x[j] - 1; x[i] := x[i] + 1;
i := i + 1; j := n;
{ Lat doan x[i..n] }
while (i < j) do
begin
t := x[i]; x[i] := x[j]; x[j] := t;
i := i + 1; j := j - 1;
end;
Next := TRUE;
end;

//

C#
static bool Next(int[] x, int n, int b) {
int i, j , b1 = b - 1;
for (j = n - 1; j >= 0; --j)
if (x[j] > 0) break;
if (j < 0) return false;
for (i = j - 1; i >= 0; --i)
if (x[i] < b1) break;
if (i < 0) return false;
--x[j]; ++x[i];
++i; j = n - 1;
int t;
while (i < j) {
t = x[i]; x[i] = x[j]; x[j] = t;

53

++i; --j;
}
return true;
}

Bi 2.2 S st sau cng ch s


Cho s t nhin x chiu di N. Hy i ch cc ch s ca x thu c s y st sau s x.
NXT.INP
6
239521

NXT.OUT
1
251239

D liu vo: tp vn bn NXT.INP


Dng u tin: s t nhin N, 2 N 1000.
Dng th hai: s x
D liu ra: tp vn bn NXT.OUT
Dng u tin: ghi 1 nu c nghim, 0: nu v
nghim. Dng th hai: s y.

Thut ton
Trc ht rng mun thu c s st sau ca x th ta phi sa cc ch s hng thp nht c
th ca x, do thut ton s duyt cc ch s ca x t phi qua tri. Ta s tm hai ch s x j v xi u tin
ca x tnh t phi qua tri tha cc iu kin sau:
Thun th phi nht: xi < xj, 1 i < j N: xi ng trc xj v nh hn xj.
Nu khng tm c hai ch s nh vy tc l x[1..n] l dy c sp gim dn th mi hon v cc
ch s ca x khng th cho ra s ln hn x: bi ton v nghim.
Nu tm c mt thun th phi nht (xi, xj) nh trn th ta sa x nh sau:
- i ch xi v xj ,
- Lt li on x[i+1..n].
Vi th d x[1..6] = (2,3,9,5,2,1) ta tm c: i = 2, x[2] = 3, j = 4, x[4] = 5.
Sau khi hon v x[i] v x[j] ta thu c, x = (2,5,9,3,2,1)
S ny cn ln, nu lt li on x[3..6] s thu c, x = (2,5,1,2,3,9). y l s cn tm.
Di y l thut ton vn dng thun th phi nht to ra s st sau theo iu kin ca u bi.
1. Tm im gy: Duyt ngc x[1..n] tm i u tin tha x[i] < x[i+1]. Nu tm c i th
thc hin bc 2, ngc li: dng thut ton vi kt qu v nghim.
2. Tm im vt: Duyt ngc x[i..n] tm j u tin tha x[i] < x[j]. rng, nu
tm c i th j lun tn ti (?).
3. Hon v x[i] v x[j],
4. Lt on x[i+1..N ].

phc tp: C N v mi ch s c thm v x l khng qu 2 ln.


Hm Next di y sa trc tip x[1..n] thu c s st sau. V s x c th c n 1000 ch s
nn ta biu din x theo kiu mng k t vi khai bo type mc1 = array[0..1000] of char. Ta
cng s dng phn t x[0] lm lnh canh v khi tr x[0] := pred('0') l k t st trc ch s 0.

(* Pascal *)
function Next(var x: mc1; n: integer): Boolean;
var i,j: integer;
t: char;
begin
Next := false; x[0] := pred('0');
{ Tim diem gay } i := n - 1;
while (x[i] >= x[i + 1]) do i := i - 1;

54

{ x[i] < x[i+1] }


if (i = 0) then exit; { Ko co diem gay: vo nghiem }
{ Tim diem vuot } j := n;
while (x[j] <= x[i]) do j := j - 1;
{ Doi cho } t := x[i]; x[i] := x[j]; x[j] := t;
{ Lat doan x[i+1..n] } i := i + 1; j := n;
while (i < j) do
begin
t := x[i]; x[i] := x[j]; x[j] := t;
i := i + 1; j := j - 1;
end;
Next := true;
end;

//

C#
static bool Next(char[] x, int n) {
int i, j ;
// Tim diem gay i
for (i = n - 2; i >= 0; --i)
if (x[i] < x[i+1]) break;
if (i < 0) return false; // vo nghiem
// Tim diem vuot
for (j = n-1; j > i; --j)
if (x[j] > x[i]) break;
char t = x[i]; x[i] = x[j]; x[j] = t; // Doi cho
// Lat doan x[i+1..n-1]
++i; j = n-1;
while (i < j){
t = x[i]; x[i] = x[j]; x[j] = t;
++i; --j;
}
return true;
}

Bi 2.3 Cc hon v
Olimpic Moscva
Lit k tng dn theo th t t in cc hon v ca cc s 1..N.
D liu vo: tp vn bn HV.INP cha
duy nht s N, 1 N 9.
D liu ra: tp vn bn HV.OUT
Mi dng mt hon v.

HV.INP

HV.OUT

1
1
2
2
3
3

2
3
1
3
1
2

3
2
3
1
2
1

Thut ton
S dng hm Next trong bi trc. Khi tr cho x l hon v n v x = (1,2,,N).
phc tp cho hm Next: 2N, cho c bi: 2N(N!).

55

Trong cc chng trnh di y ta xy dng cc hm Next khng c tham bin nhm mc ch y


nhanh qu trnh tnh ton. Nh vy, d liu c cho di dng cc bin tng th, bao gm n - chiu di
ca cc hon v, x[0..n1] - mng cha hon v.

(*

Pascal

*)

(***************************************
Liet ke cac hoan vi cua 1..N
theo thu tu tang dan
***************************************)
program CacHoanVi;
uses crt;
const
bl = #32; mn = 10; fn = 'HV.INP'; gn = 'HV.OUT';
type
mb1 = array[0..mn] of byte;
var
x: mb1; { chua hoan vi }
n: byte; { Len(x) }
f,g: text; { input, output files }
procedure Doc;
begin
assign(f,fn); reset(f);readln(f,n); close(f);
end;
function Next: Boolean;
var i,j,t : byte;
begin
Next := false;
{ Tim diem gay }
i := n - 1;
while (x[i] >= x[i + 1]) do i := i - 1;
{ x[i] < x[i+1] }
if (i = 0) then exit;
j := n;
while (x[j] <= x[i]) do j := j - 1;
t := x[i]; x[i] := x[j]; x[j] := t;
i := i + 1; j := n;
while (i < j) do
begin
t := x[i]; x[i] := x[j]; x[j] := t;
i := i + 1; j := j - 1;
end;
Next := true;
end;
procedure Run;
var i: byte;
begin
Doc; x[0] := 0; // Dat linh canh
assign(g,gn); rewrite(g);
for i := 1 to n do x[i] := i;// Hoan vi don vi
repeat
for i := 1 to n do write(g,x[i],bl);
writeln(g);
until not Next;
close(g);
end;
BEGIN

56

Run;
END.

//

C#

using System;
using System.IO;
namespace SangTao2 {
/*--------------------------------------*
Cac Hoan Vi
*
Liet ke cac hoan vi (1,2,...,n)
*
theo trat tu tu dien tang dan
* -------------------------------------*/
class CacHoanVi {
const string fn = "hv.inp";
const string gn = "hv.out";
static char[] x; // chua cac hoan vi
static int n; // so phan tu
static void Main(){
Run();
Console.ReadLine();
} // Main
static void Run() {
n = int.Parse((File.ReadAllText(fn)).Trim());
x = new char[n + 1];
for (int i = 0; i < n; ++i)
x[i] = (char) ('1' + i);
StreamWriter g = File.CreateText(gn);
do {
for (int i = 0; i < n; ++i) g.Write(x[i]);
g.WriteLine();
} while (Next());
g.Close();
XemKetQua();
}
// Hien thi du lieu de kiem tra
static void XemKetQua() {
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine(File.ReadAllText(gn));
}
static bool Next(){
int i, j;
// Tim diem gay i
for (i = n - 2; i >= 0; --i)
if (x[i] < x[i + 1]) break;
if (i < 0) return false; // vo nghiem
// Tim diem vuot
for (j = n - 1; j > i; --j)
if (x[j] > x[i]) break;
char t = x[i]; x[i] = x[j]; x[j] = t; // Doi cho
// Lat doan x[i+1..n-1]
++i; j = n - 1;
while (i < j){
t = x[i]; x[i] = x[j]; x[j] = t;
++i; --j;
}
return true;

57

}
} // CacHoanVi
} // SangTao2

Bi 2.4 T hp
Lit k cc t hp chp K ca N phn t 1..N theo th t t in tng dn.
TOHOP.INP

5 3

D liu vo: tp vn bn TOHOP.INP

TOHOP.OUT

1
1
1
1
1
1
2
2
2
3

2
2
2
3
3
4
3
3
4
4

3
4
5
4
5
5
4
5
5
5

Dng u tin: hai s N v K cch nhau qua du cch,


1 N 9, K N.
D liu ra: tp vn bn TOHOP.OUT
Mi dng mt t hp, cc s trn cng dng cch nhau
qua du cch.

Thut ton

Phng n 1. Ta khi tr cho mng x[1..K] l t hp nh


nht (1,2,,K). Sau ta dng hm Next sinh ra t hp st
sau ca x. Hm Next hot ng theo 2 pha nh sau:
Pha 1. D. Duyt ngc t K qua tri b qua nhng phn
t mang gi tr N2, N1, N ng cui mng. Nu sau khi d x
khng cn phn t no th kt thc vi Next = false vi ngha l
st sau t hp x khng cn t hp no. Th d, nu N = 7, K = 5,
x[1..5] = (2,3,5,6,7) th sau khi d ba phn t cui ca x ta thu
c i = 2, x[1..2] = (2,3). iu ny cho bit s cn t hp st sau.
Pha 2. Xp.
2.1. Tng phn t x[i] thm 1 n v. Tip tc vi th d trn ta thu c x[1..2] = (2,4)
2.2. Xp tip vo x cho K phn t theo trt t tng dn lin tc. Tip tc vi th d trn ta thu
c x[1..5] = (2,4,5,6,7).
Ta s dng phn t x[0] = N lm lnh canh.

(* Pascal, Phuong an 1 *)
function Next: Boolean;
var i, j, b: integer;
begin
Next := false; x[0] := N;
{ Pha 1. Do }
i := k; b := n - k;
while (x[i] = b + i) do i := i - 1;
if (i = 0) then exit;
{ Pha 2. Xep }
x[i] := x[i] + 1;
for j := i + 1 to k do x[j] := x[j-1] + 1;
Next := true;
end;
phc tp: cho hm Next: 2N, cho c bi: 2N.CNK = (2N. N!) / (K! (N-K)!) .
Phng n 2.
Ta ci tin hm Next nh sau. Gi s sau pha 1 ta thu c v tr i tha x[i]
nk+i. Ta gi v tr ny l v tr cp nht v s iu khin n thng qua mt bin v. Ta khi tr cho x v v
nh sau
for i := 1 to k do x[i] := i;
if (x[k] = n) then v := 0 else v := k;
Sau mi ln gi hm Next ta kim tra

58

Nu v = 0 th dng hm Next.
Nu v 0 ta thc hin pha 2 sau chnh li gi tr ca v nh sau:
Nu x[k] = n th tc l x[v..k] = (nkv, ..., n1, n) th ln gi Next tip theo s cp nht ti v tr v-1,
ngc li, nu x[k] n th ln gi Next tip theo s cp nht ti v tr k.
phc tp: cho hm Next: N. Cho c bi: N.CNK = (N. N!) / (K! (N-K)!).

(*

Pascal,

Phng n 2

*)

(***************************************
To hop chap k cua n phan tu
PHUONG AN 2
***************************************)
program ToHopKN;
uses crt;
const
bl = #32; mn = 10; fn = 'TOHOP.INP'; gn = 'TOHOP.OUT';
type
mb1 = array[0..mn] of byte;
var
x: mb1;
n, k, v: byte;
f,g: text;
procedure Doc;
begin
assign(f,fn); reset(f); readln(f,n,k); close(f);
end;
function Next: Boolean;
var i: byte;
begin
Next := false;
if (v = 0) then exit;
{ Pha 2. Xep }
x[v] := x[v] + 1;
for i := v + 1 to k do x[i] := x[i-1] + 1;
if (x[k] = n) then v := v - 1 else v := k;
Next := true;
end;
procedure Run;
var i: byte;
begin
Doc;
assign(g,gn); rewrite(g);
for i := 1 to k do x[i] := i;
if (x[k] = n) then v := 0 else v := k;
repeat
for i := 1 to k do write(g,x[i],bl);
writeln(g);
until not Next;
close(g);
end;
BEGIN
Run;
END.

//

C#

using System;

59

using System.IO;
namespace SangTao2 {
/*-------------------------------To hop (Phuong an 2)
Liet ke cac to hop chap k
cua n phan tu 1, 2, , n
-------------------------------*/
class ToHop2 {
const string fn = "ToHop.inp";
const string gn = "ToHop.out";
static int[] x;
static int n = 0; // so phan tu nen
static int k = 0; // so phan tu trong 1 to hop
static int v = 0; // vi tri cap nhat trong x
static void Main() {
GhiToHop(); XemKetQua();
Console.WriteLine("fini"); Console.ReadLine();
} // Main
// Doc lai cac tep inp va out de kiem tra
static void XemKetQua() {
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine(File.ReadAllText(gn));
}
static bool Next(){
if (v == 0) return false;
++x[v];
for (int i = v + 1; i <= k; ++i) x[i] = x[i - 1] + 1;
v = (x[k] == n) ? v - 1 : k;
return true;
}
static void Doc(){
char[] cc = new char[] { '\n', ' ', '\t', '\r' };
string[] ss = (File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries);
n = int.Parse(ss[0]); k = int.Parse(ss[1]);
}
static void GhiToHop(){
Doc();
// Tao tep ket qua ToHop.out
StreamWriter g = File.CreateText(gn);
// Khoi tri;
x = new int[k + 1];
for (int i = 1; i <= k; ++i) x[i] = i;
v = (x[k] == n) ? 0 : k;
do {
for (int i = 1; i <= k; ++i) g.Write(x[i] + " ");
g.WriteLine();
} while (Next());
g.Close();
}
} // ToHop2
} // SangTao2
Ch Bn c lu rng thut ton trn cho ra dy sp tng cc t hp v trong mi t hp cc thnh
phn cng c sp tng.

60

Bi 2.5 S Kapreka
S Kapreka mang tn nh ton hc n v c m t nh sau. l s t nhin x vit trong h
m B c ng K ch s khc nhau i mt v x = x x, trong x v x ln lt l cc s thu c
bng cch sp li cc ch s ca s x theo trt t gim v tng dn. Vi mi cp gi tr B v K hy tm
mt s Kapreka.
KAPREKA.INP

10 4

KAPREKA.OUT

6174

D liu vo: tp vn bn KAPREKA.INP


Dng u tin: hai s B v K cch nhau qua du cch,
2 B 10, K < B.
D liu ra: tp vn bn KAPREKA.OUT
S x vit trong h m B.
B d liu trn cho bit: Trong h m thp phn (B =
10), x = 6174 l s Kapreka c 4 ch s (khc nhau i mt),
x'' - x' = 7641 1467 = 6174 = x.

Thut ton
Ta da vo thut ton t hp Next ca bi trc, sinh ln
Kaprekar D. R. (1905-1986) nh
lt cc s K ch s trong h b. Lu rng h m b s dng b
ton hc n say m l thuyt s
ch s 1..(b1). Vi mi s x c sinh ra theo thut ton Next
t nh. Sau khi tt nghip i hc
ta tnh hiu y = x x, trong x l s thu c bng cch sp
Tng hp Bombay nm 1929 ng
li cc ch s ca x theo trt t gim dn v x tng dn. Nu y
lm gio vin ph thng ti Devlali,
ch cha cc ch s ca x th y chnh l mt s Kapreka. Do cc
n . ng vit nhiu bi kho cu
t hp x c sinh ra cha cc ch s i mt khc nhau v
ni ting v l thuyt s, ma phng
c sp tng, nn ta lun c x'' = x.
v cc tnh cht k l ca th gii s.
tm hiu ca hai s trong h b ta nn biu din ngc
cc s di dng mng K phn t nhn cc gi tr trong khong 0..b-1. Th d s x = 1234 trong h 10 s
c biu din l x[1..4] = (4,3,2,1).
Gi s x = (x1, x2,,xK) v y = (y1, y2,,yK). Ta tnh hiu z = x y = (z1, z2,,zK) theo qui tc
sau:
Tnh z = x + y* + 1, trong y* l dng b (b1) ca y.
Sau ta b i s nh cui cng.
Dng b (b 1) y* = (y1*, y2*,,yK*) ca s y c tnh nh sau: yi* = (b 1) yi, i = 1..K.
Th d, tnh 9217 468 trong h 10. Ta c x[1..4] = (7,1,2,9), y[1..4] = (8,6,4,0), do y*[1..4] =
(1,3,5,9). Vy x y = x + y* + 1 = (7,1,2,9) + (1,3,5,9) + (1,0,0,0) = (9,4,7,8). Kt qu l, 9217 468 =
8749.
Qui tc trn c gii thch nh sau. Xt cc s trong h m b. K hiu z = b1, khi s (z,
z,,z) gm K ch s z chnh l bK 1 v y* = (bK1)y. Khi , x y = x y + (bK 1) + 1 bK = x +
((bK1)y) + 1 bK = x + y* + 1 bK. Vic b s nh cui cng tng ng vi php tr bK vo kt qu.
Di y l th tc tnh hiu z = x y cho cc s vit ngc c ti a K ch s trong h b.
procedure Hieu;
var i,c,t: integer;
begin
c := 1; { so nho }
for i := 1 to K do
begin
t := x[i] + ((b-1)-y[i]) + c;
z[i] := t mod b;
c := t div b;
end;
end;

61

rng php cng hai s mt ch s trong h m b > 1 bt k cho s nh ti a l 1. Ngoi ra do cc


php ton div v mod thc hin lu hn cc php cng v tr nn ta c th vit li th tc trn nh sau.
procedure Hieu;
var i,c,t: integer;
begin
c := 1;
for i := 1 to K do
begin
t := x[i] + (b-1-y[i]) + c;
if (t >= b) then
begin z[i] := t b; c := 1; end
else begin z[i] := t; c := 0; end;
end;
end;
Vi s x c K ch s sp tng tc l dng vit ngc ca x ta c th thc hin php tr y = x x bng
cc thao tc trn chnh x theo hai chiu duyt xui v ngc. Khi thc hin php ly hiu ta cng ng thi
kim tra xem mi ch s ca y c xut hin ng mt ln trong x hay khng. Nu ng, ta cho kt qu l
true, ngc li, ta cho kt qu false. thc hin vic ny ta dng mng d[1..K] nh du s xut hin
ca cc ch s trong x v y.
(*-----------------------------y = x'' - x' (he dem B)
-------------------------------*)
function Hieu: Boolean;
var i,c,t: integer;
begin
fillchar(d,sizeof(d),0); { mang danh dau }
Hieu := false;
{ Ghi nhan cac xuat hien cua x[i] }
for i := 1 to k do d[x[i]] := 1;
c := 1; { c: so nho }
for i := 1 to k do
begin
t := x[i] + (b - 1 - x[k-i+1]) + c;
if (t >= b) then
begin y[i] := t - b; c := 1; end
else begin y[i] := t; c := 0; end;
if (d[y[i]] = 0) then exit;
if (d[y[i]] = 1) then d[y[i]] := 0;
end;
Hieu := true;
end;
Di y cung cp 15 th d bn c test chng trnh. Kt qu 0 cho bit khng tn ti s
Kapreka cho trng hp .
NN B K p s

N B K p s
N

N
N

K p s

4 3 132

6 8 2 25

1
1

7 0

5 4 0

7 8 3 374

1
2

8 0

6 3 253

8 8 7 6417532 1
3

10 3 495

62

6 4 0

6 5 41532

9 9 5 62853
1 9 6 0
0

1
4

10 4 6174

1
5

10 9 864197532

15 th d v cc s Kapreka

(*

Pascal

*)

(***************************************
So Kapreka
***************************************)
program SoKapreka;
uses crt;
const mn = 11; fn = 'KAPREKA.INP'; gn = 'KAPREKA.OUT';
type mb1 = array[0..mn] of byte;
var x,y,d: mb1;
b,k,b1,v: integer;
{------------------------------------------b - he dem
k - so chu so
b1 - chu so lon nhat trong he b, b1 = b-1
v - bien kiem soat cho ham Next
---------------------------------------------}
f,g: text;
procedure Doc;
begin assign(f,fn); reset(f); readln(f,b,k); close(f);
b1 := b-1; { Chu so cao nhat trong he dem b }
end;
function Next: Boolean;
var i: integer;
begin
Next := false;
if (v = 0) then exit;
x[v] := x[v] + 1;
for i := v + 1 to k do x[i] := x[i-1] + 1;
if (x[k] = b1) then v := v - 1 else v := k;
Next := true;
end;
(*-----------------------------y = x'' - x'
-------------------------------*)
function Hieu: Boolean;
var i,c,t: integer;
begin
fillchar(d,sizeof(d),0);
Hieu := false;
{ Ghi nhan cac xuat hien cua x[i] }
for i := 1 to k do d[x[i]] := 1;
c := 1; { c: so nho }
for i := 1 to k do
begin
t := x[i] + (b1 - x[k-i+1]) + c;
if (t > b1) then
begin t := t - b; c := 1; end
else c := 0;

63

if (d[t] = 0) then exit; { t ko xuat hien trong x }


y[i] := t; d[t] := 0;
end;
Hieu := true;
end;
function Kapreka: Boolean;
var i: integer;
t: Boolean;
begin
Kapreka := true;
{ Khoi tri x la to hop tang nho nhat }
{ x[1..k] = (0,1,...,k-1) }
for i := 1 to k do x[i] := i-1;
if (x[k] = b1) then v := 0 else v := k;
repeat
if (Hieu) then exit;
until not next;
Kapreka := false;
end;
procedure Run;
var i: byte;
begin
Doc;
assign(g,gn); rewrite(g);
if (Kapreka) then
for i := k downto 1 do write(g,y[i])
else write(g,0);
writeln(g); close(g);
end;
BEGIN
Run;
END.

//

C#

using System;
using System.IO;
namespace SangTao2 {
/*------------------------------------------*
So Kapreka
*
x'' - x' = x
*
x'' - so giam
*
x' - so tang
* ------------------------------------------*/
class Kapreka {
const string fn = "Kapreka.inp";
const string gn = "Kapreka.out";
static int[] x; // so x
static int[] y; // y = x'' - x'
static int[] d;
static int b; // he dem
static int k; // so chu so
static int b1; // b-1: chu so cao nhat trong he b
static int v; // bien cam canh
static void Main() {
Doc(); Ghi(Kap()); XemKetQua();
Console.WriteLine("\n fini");

64

Console.ReadLine();
} // Main
static void Ghi(int ket){
StreamWriter g = File.CreateText(gn);
if (ket == 0) g.WriteLine(0);
else for (int i = k; i > 0; --i) g.Write(y[i]);
g.Close();
}
// Doc lai cac tep inp va out de kiem tra
static void XemKetQua(): t vit
static bool Next() {
if (v == 0) return false;
++x[v];
int j = x[v] + 1;
for (int i = v + 1; i <= k; ++i, ++j) x[i] = j;
v = (x[k] == b1) ? v - 1 : k;
return true;
}
static void Doc() {
char[] cc = new char[] { '\n', ' ', '\t', '\r' };
string[] ss = (File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries);
b = int.Parse(ss[0]); // he dem
k = int.Parse(ss[1]); // so chu so
b1 = b - 1; // chu so cao nhat cua he dem b
}
// y = x'' - x'
static bool Hieu() {
int c = 1, t = 0;
Array.Clear(d, 0, d.Length);
for (int i = 1; i <= k; ++i) d[x[i]] = 1;
for (int i = 1; i <= k; ++i){
t = x[i] + (b1 - x[k - i + 1]) + c;
if (t > b1) { c = 1; t = t - b; }
else c = 0;
if (d[t] == 0) return false;
y[i] = t; d[t] = 0;
}
return true;
}
static int Kap() {
// Khoi tri;
x = new int[k + 1];
y = new int[k + 1];
d = new int[b];
for (int i = 1; i <= k; ++i) x[i] = i - 1;
v = (x[k] == b1) ? 0 : k;
do {
if (Hieu()) return 1;
} while (Next());
return 0;
}
} // class Kapreka
} // SangTao2

Ch thch
Bn c th s dng thut ton sau y:

65

Khi tr: To s x h b gm k ch s khc nhau;


Lp t 1 n bk 1
Tnh y = x'' x';
Nu x = y th cho kt qu x l s Kapreka; stop;
Nu khng gn x := y;
Xong lp.

Bi 2.6 Kha vng


Mt kha gm M vng ch v N vng s. Mi vng ch hoc s cha cc gi tr bin thin t gii
hn nh nht a n gii hn ln nht b. Hy lit k tng dn theo trt t t in cc gi tr c th c ca
kha.
KHOA.INP

1
B
2
0

2
C
3
2

KHOA.OUT

12
B20
B21
B22
B30
B31
B32
C20
C21
C22
C30
C31
C32

D liu vo: tp vn bn KHOA.INP


Dng u tin: hai s t nhin M v N, 1 M, N 5.
Dng th i trong s M+N dng tip theo: gii hn a i v bi
cho cc vng kha.
D liu ra: tp vn bn KHOA.OUT
Dng u tin: Tng s kh nng.
T dng th hai tr i: mi dng mt gi tr kha lit k
tng dn theo trt t t in. Cc k t ch v s trong mi kha
c vit lin nhau, khng c du cch gia. Cc gi tr ch
c ly t bng ch HOA ting Anh.

Thut ton
Phng php: duyt ton b cc t hp.
Nu ton b N vng kha u ch cha cc ch s vi gii
hn bit trc t cn di a[i] n cn trn b[i] , i = 1..N th ta
dng hm Next sinh ra ln lt cc t hp N phn t c[1..N] nh
sau.

Khi tr: c[1..N] l t hp nh nht cha ton cn di:


c[i] := a[i], i = 1..N.
X l:
repeat
Ghi t hp c[1..N];
until not Next;
Mi ln gi hm Next ta thc hin ging nh php m: Duyt ngc c[1..N] vi mi c[i] = b[i] ta
t li c[i] := a[i]. Gp c[i] u tin tha iu kin c[i] < b[i] th tng vng kha i thm 1 nc. Nu khng
gp phn t i nh vy th chng t x l xong t hp cao nht.
Vic cn li l chuyn cc vng ch sang vng s tng ng.
phc tp: (b1-a1+1)(b2-a2+1)...(bv-av+1), v = M+N.

(*

Pascal

*)

(****************************************
Khoa Vong
*****************************************)
program KhoaVong;
uses crt;
const mn = 20;

66

bl = #32; nl = #13#10; fn = 'KHOA.INP'; gn = 'KHOA.OUT';


ChuCai = ['A'..'Z'];
type mi1 = array[0..mn] of integer;
var m,n: integer;
a,b,c: mi1;
f,g: text;
m: longint;
procedure Doc;
var i: integer;
c: char;
begin
assign(f,fn); reset(f); readln(f,m,n);
n := m + n;
for i := 1 to m do
begin
repeat
read(f,c);
until c in ChuCai;
a[i] := ord(c) - ord('A');
repeat
read(f,c);
until c in ChuCai;
b[i] := ord(c) - ord('A');
end;
for i := m + 1 to n do read(f,a[i],b[i]);
close(f);
m := 1;
for i := 1 to n do m := m * (b[i] - a[i] + 1);
end;
function Min(a,b: integer): integer;
begin
if (a < b) then Min := a else Min := b;
end;
function Next: Boolean;
var i: integer;
begin
Next := false;
i := n;
while (c[i] = b[i]) do
begin
c[i] := a[i];
i := i - 1;
end;
if (i = 0) then exit;
c[i] := c[i] + 1;
Next := true;
end;
procedure Duyet;
var i: integer;
begin
for i := 1 to n do c[i] := a[i];
c[0] := -1;
assign(g,gn); rewrite(g); writeln(g,m);
repeat
for i := 1 to m do write(g,chr(ord('A')+c[i]));
for i := m + 1 to n do write(g,c[i]);
writeln(g);

67

until not Next;


close(g);
end;
BEGIN
Doc; Duyet;
END.

//

C#

using System;
using System.IO;
namespace SangTao2 {
/*------------------------------------------*
Khoa Vong
* ------------------------------------------*/
class KhoaVong {
const string fn = "Khoa.inp";
const string gn = "Khoa.out";
static int [] x; // to hop
static int[] vmin; // can duoi
static int[] vmax; // can tren
static int m; // so luong vong chu
static int n; // so luong vong so
static int mn; // m+n
static void Main() {
Doc(); Ghi(); XemKetQua(); Console.ReadLine();
} // Main
// Doc lai cac tep inp va out de kiem tra
static void XemKetQua(): t vit
static bool Next() {
int i;
for (i = mn - 1; i >= 0; --i)
if (x[i] == vmax[i]) x[i] = vmin[i];
else break;
if (i < 0) return false;
++x[i];
return true;
}
static void Doc() {
char [] cc = new char [] {'\n',' ','\t','\r'};
string [] ss = (File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries);
int k = 0;
m = int.Parse(ss[k++]); // m vong chu
n = int.Parse(ss[k++]); // n vong so
mn = m + n;
vmin = new int [mn];
vmax = new int [mn];
for (int i = 0; i < m; ++i) {
vmin[i] = (int)ss[k++][0] - (int)'A';
vmax[i] = (int)ss[k++][0] - (int)'A';
}
for (int i = m; i < mn; ++i) {
vmin[i] = int.Parse(ss[k++]);
vmax[i] = int.Parse(ss[k++]);
}
}

68

static void Ghi() {


StreamWriter g = File.CreateText(gn);
// khoi tri x
x = new int[mn];
for (int i = 0; i < mn; ++i) x[i] = vmin[i];
do {
for (int i = 0; i < m; ++i)
g.Write((char)(x[i] + (int)'A'));
for (int i = m ; i < mn; ++i)
g.Write(x[i]);
g.WriteLine();
} while (Next());
g.Close();
}
} // KhoaVong
} // SangTao2

Bi 2.7 Tr tin
ng.

C N loi tin mnh gi mi v s lng si , i = 1..N. Xc nh s lng mi loi c th tr li V

TRATIEN.INP

6 156
1 2 5 10 20 50
4 7 2 3 6 2

TRATIEN.OUT

0 3 0 0 5 1

D liu vo: tp vn bn TRATIEN.INP


Dng u tin: hai s t nhin N v V, 2 N 15.
Dng th hai: N s t nhin m1, m2,,mN.
Dng th ba: N s t nhin s1, s2,,sN.
D liu ra: tp vn bn TRATIEN.OUT

N s t nhin c1, c2,,cN th hin s lng t tin


mi loi cn tr, c1m1 + c2m2 + + cNmN = V. Nu v
nghim: ghi s 0.
Trong cc tp *.INP v *.OUT cc s trn cng dng cch nhau qua du cch.

Thut ton
y l loi ton Balo vi d liu nh v trong thc t s mnh gi khng nhiu, th d, tin Vit ch
c cc loi sau y l thng dng 100, 200, 500, 1.000, 2.000, 5.000, 10.000, 20.000, 50.000, 100.000,
200.000, 500.000. Nu tnh theo n v 100 ng th ta c th vit li dy trn cho gn hn nh sau:
1, 2, 5, 10, 20, 50, 100, 200, 500, 1.000, 2.000, 5.000.
Ta duyt cc t hp s t tin phi tr cho mi loi mnh ga, cn di l 0 cn trn l min(s i, v div
mi) v tr li v ng bng loi mnh gi mi ta dng ti a (v div mi) t.
phc tp: (b1-a1+1)(b2-a2+1)...(bv-av+1), v = M+N.
Ch : Sau ny ta s xy dng thut ton tt hn cho bi ton tr tin. Thut ton ny da trn mt
s kin thc s hc.

(*

Pascal

*)

(****************************************
Tra tien
*****************************************)
program TraTien;
uses crt;
const mn = 20; bl = #32; nl = #13#10;
fn = 'TRATIEN.INP'; gn = 'TRATIEN.OUT';
type mi1 = array[0..mn] of integer;

69

(*---------------------------------n so luong cac loai tien


v so tien can tra lai
vt gia tri tam thoi
m[1..n] cac menh gia
s[1..n] so luong to tien
c[1..n] so luong can chon
------------------------------------*)
var n,v,vt: integer;
m,s,c: mi1;
f,g: text;
procedure Doc;
var i: integer;
begin
assign(f,fn); reset(f); readln(f,n,v);
for i := 1 to n do read(f,m[i]);
for i := 1 to n do read(f,s[i]);
close(f);
end;
function Min(a,b: integer): t vit
function Next: Boolean;
var i: integer;
begin
Next := false;
i := n;
while (c[i] = s[i]) do
begin
vt := vt - c[i] * m[i];
c[i] := 0;
i := i - 1;
end;
if (i = 0) then exit;
c[i] := c[i] + 1;
vt := vt + m[i];
Next := true;
end;
function Duyet: Boolean;
var i: integer;
begin
{ Khoi tri }
for i := 1 to n do
begin
s[i] := min(s[i],v div m[i]);
c[i] := 0;
end;
c[0] := -1; vt := 0; { tong gia tri cua 1 phuong an }
Duyet := true;
repeat
if (vt = v) then exit;
until not Next;
Duyet := false;
end;
procedure Run;
var i: integer;
begin
Doc; assign(g,gn); rewrite(g);
if (Duyet) then

70

for i := 1 to n do write(g,c[i],bl);
else writeln(g,0);
close(g);
end;
BEGIN
Run;
END.

// C#
using System;
using System.IO;
namespace SangTao2 {
/*------------------------------------------*
Tra Tien
* ------------------------------------------*/
class TraTien {
const string fn = "TraTien.inp";
const string gn = "TraTien.out";
static int[] c; // phuong an dang duyet
static int[] s; // so luong to tien
static int[] m; // menh gia
static int n; // so luong menh gia
static int v; // tong so tien can tra
static int t; // tong so tien cua 1 phuong an
static void Main() {
Doc();
int kq = XuLi();
Ghi(kq);
} // Main
static bool Next() {
int i = n;
while (c[i] == s[i]) { t -= c[i] * m[i]; c[i] = 0; --i; }
if (i == 0) return false;
++c[i]; t += m[i]; return true;
}
static void Doc() {
char[] cc = new char[] { '\n', ' ', '\t', '\r' };
string[] ss = (File.ReadAllText(fn)).Split(cc,
StringSplitOptions.RemoveEmptyEntries);
int k = 0;
n = int.Parse(ss[k++]); // n so luong tien
v = int.Parse(ss[k++]); // v so tien can tra lai
m = new int[n + 1]; // cac menh gia
s = new int[n + 1]; // so luong to moi loai
for (int i = 1; i <= n; ++i)
m[i] = int.Parse(ss[k++]);
for (int i = 1; i <= n; ++i)
s[i] = Min(v/m[i], int.Parse(ss[k++]));
}
static int Min(int a, int b) { return (a < b) ? a : b; }
static int XuLi() {
c = new int[n + 1];
for (int i = 1; i <= n; ++i) c[i] = 0;
t = 0;
do { if (t == v) return 1; } while (Next());
return 0;

71

}
static void Ghi(int kq) {
StreamWriter g = File.CreateText(gn);
if (kq == 0) g.WriteLine(kq);
else for (int i = 1; i <= n; ++i) g.Write(c[i] + " ");
g.Close();
}
} // TraTien
} // SangTao2

Bi 2.8 Dy Farey
Cho s t nhin N > 0. hy lit k theo trt t tng dn cc phn s t / m tha ng thi cc
tnh cht sau:
- t / m l phn s ti gin bin thin trong khong 0..1,
- m bin thin trong khong 1..N.
FAREY.INP

FAREY.OUT

D liu vo: tp vn bn FAREY.INPcha s N.


D liu ra: tp vn bn FAREY.OUT

11
0 1
1 5
1 4
1 3
2 5
1 2
3 5
2 3
3 4
4 5
1 1

Dng th nht: D s lng cc phn s trong dy.


T dng th hai: mi dng hai s t nhin t m ghi cch
nhau qua du cch, th hin mt phn s trong dy sp
tng.

Thut ton
Nu sinh ln lt cc phn s (PS) ri sp xp th
kh tn b nh v ti a phi dnh b nh lu tr
n2 PS.
Phng n 1. Nu
t/m v a/b l hai
PS s lin tip
trong dy Farey
th

Farey l nh a cht hc ngi


Anh. ng m t dy phn s trn
vo nm 1816.

a/b = min { x/y | x/y > t/m, y = 1..n, x y, (x,y) = 1 }


trong (x,y) l c chung ln nht ca x v y.
Cc PS x/y trong tp trn c gi l cc ng vin. Ta s c cng t ng vin cng tt.
Vi y = 1, do x y nn ta c ngay PS 1/1 l phn t ln nht trong dy.
Vi mi y = 2..n ta xt PS x/y l PS u tin ln hn t/m.
Ta c t t/m < x/y ta suy ra mx > ty nn x > (ty div m). Nu bit m ta chn x = (ty div m) +1 s thu
c PS x/y tha ng thi cc tnh cht sau:
-1mn
- x/y l PS u tin ln hn t/m.
c t trn c thu gn li vi n1 ng vin nh sau,
a/b = min { x/y | y = 2..n, x = (ty div m) + 1 }
Nh vy, nu sinh c PS t/m cho dy Farey th PS tip theo a/b s c chn l PS nh nht
trong tp n1 PS ni trn. rng 0/1 l PS u tin v 1/1 l PS cui cng ca dy Farey. Th tc
Next(n,t,m) trong phng n 1 s xc nh PS a/b st sau PS t/m trong dy Farey. Gi tr tm c s t
ngay trong t/m.

72

phc tp. Xut pht t PS u tin 0/1, mi ln ta phi sinh ra n 1 ng vin t chn ra 1
PS trong dy. Nu dy c s PS th ta phi thc hin s(n1) php ton trn cc PS. Gi tr max ca s l n2.
Vy phc tp tnh ton vo c n3.

Bnh lun
Nu t PS t/m trong dy Farey v gi tr mu s y trong khong 2..n cho trc ta sinh ra PS x/y
thng qua h thc x = (ty div m) + 1 th PS x/y c th cha ti gin. Th d, vi n = 15, t/m = 3/4, y = 12 ta
c x = (ty div m)+1 = 10 th PS 10/12 khng ti gin do ta cn gi th tc RutGon gin c PS x/y.
V khng tnh trc c s lng cc PS trong dy nn ta cn m dn v ghi tm dy PS vo tp
FAREY.TMP. Sau m tp FAREY.OUT ghi s lng s v chuyn d liu t tp FAREY.TMP sang tp
FAREY.OUT, cui cng xa tp FAREY.TMP.
Phng n 2. Ta c th sinh dn cc phn t cho dy Farey nh sau. Cho hai PS a/b v c/d, PS
(a+c)/(b+d) c gi l PS trung bnh ca hai PS ny.
Nhn xt. Nu t1 / m1 , t2 / m2 , t3 / m3 l ba PS lin tip trong dy Farey th PS gia l PS trung
bnh ca hai PS kia.
Ta c thut ton sau:
Xut pht vi mu s m = 1 ta c dy 2 PS: 0/1, 1/1.
Vi mi mu s m = 2..n ta sinh cc PS trung bnh c mu s m ca hai PS k nhau trong dy trc
v xen PS ny vo gia hai PS sinh ra n dn vo trong dy kt qu.
m = 2: thm cc PS trung bnh vi mu bng 2: 0/1, 1/2 , 1/1.
m = 3: thm cc PS trung bnh vi mu bng 3: 0/1, 1/3, 1/2, 2/3, 1/1.
...
Cc phn s mi sinh trong mi ln duyt c gch di.
Ta dng hai mng: a lu cc PS ca dy trc, b lu cc PS ca dy sau. Sau mi bc lp ta
chuyn b qua a. D liu c m t nh sau:
const mn = 1000;
type
PS = record tu,mau: byte end;
mps = array[0..mn] of PS; { mng cc PS }
var a,b: mps;
phc tp. Thi gian: n3, min nh : 2 mng kch thc n2.
Phng n 3. Ta s dng mt s tnh cht ca dy Farey tip tc ci tin thut ton.
Nu t1 / m1 , t2 / m2 , t3 / m3 l ba PS lin tip trong dy Farey th
1. t2m1 t1m2 = 1,
2. m1 + m2 > n,
3. t2 / m2 = (t1 + t3) / (m1 + m3),
4. t3 = vt2 t1, m3 = vm2 m1 vi v = (m1 + n) div m2.
T tnh cht 4 ta suy ra ngay cch xc nh PS t3/m3 thng qua hai PS st trc.
Cc trnh di y minh ha 3 phng n vi cc kt qu hin th trn mn hnh bn c c th
theo di.

(*

Pascal

*)

(*------------------------------------*
Ba phuong an cho bai Day Farey
*-------------------------------------*)
uses crt;
const bl = #32; nl = #13#10;
var n: integer;
{ Uoc chung lon nhat cua hai so tu nhien a, b }
function Ucln(a,b:integer):integer;

73

var r: integer;
begin
while b > 0 do begin r := a mod b; a := b; b:=r end;
Ucln:=a;
end;
{ Rut gon PS a/b thanh PS t/m }
procedure RutGon(a,b:integer; var t,m:integer);
var d:integer;
begin d :=Ucln(a,b); t := a div d; m := b div d; end;
{ Tim PS sat sau PS t/m, ket qua dat trong t/m }
function Next(n: integer; var t,m: integer): Boolean;
var a,b,x,y: integer;
begin
if (t+m=2) then begin Next := false; exit end;
a := 1; b := 1;
for y := 2 to n do
begin
x := t*y div m + 1;
if a*y > b*x then begin a := x; b:=y end;
end;
RutGon(a,b,t,m); Next := true;
end;
procedure Farey1(n: integer);
var t,m,d:integer;
begin
writeln(nl,'Farey1'); d := 0;
t := 0; m := 1;
repeat
write(t,'/',m,bl); inc(d);
until not Next(n,t,m);
writeln(nl,'Total: ',d,' PS');
readln;
end;
procedure Farey2(n: byte);
const mn = 1000;
type PS = record tu,mau: byte end;
mps1 = array[0..mn] of PS;
var a,b: mps1; { 2 day PS a , b }
d,k,i,m:integer;
begin
writeln(nl,'Farey2'); d := 2;
a[1].tu := 0; a[1].mau := 1; { PS dau day }
a[2].tu := 1; a[2].mau := 1; { PS thu hai }
for m:=2 to n do
begin
k := 0; inc(k); b[k] := a[k];
for i := 2 to d do
begin
if a[i].mau+a[i-1].mau = m then
begin
inc(k); b[k].tu := a[i-1].tu + a[i].tu;
b[k].mau := a[i-1].mau + a[i].mau;
end;
inc(k); b[k] := a[i];
end;
a := b; d := k;
end;

74

for i := 1 to d do write(a[i].tu,'/',a[i].mau,bl);
writeln(nl,'Total ',d,' PS');
readln;
end;
procedure Farey3(n: integer);
var t1,m1,t2,m2,t3,m3,v,d: integer;
begin
writeln(nl,'Farey3'); d := 2;
t1 := 0; m1 := 1; { PS dau day }
t2 := 1; m2 := n; { PS thu hai }
write(t1,'/',m1,bl,t2,'/',m2,bl);
while (t2 + m2 <> 2) do
begin
v := (m1+n) div m2;
t3 := v*t2 - t1; m3 := v*m2 - m1;
write(t3,'/',m3,bl); inc(d);
t1 := t2; t2 := t3;
m1 := m2; m2 := m3;
end;
writeln(nl,'Total ',d,' PS'); readln;
end;
BEGIN
n := 5;
Farey1(n); Farey2(n); Farey3(n);
END.

// C#
using System;
using System.IO;
namespace SangTao2 {
/*-------------------------------------------*
Ba phuong an cho bai Day Farey
* ------------------------------------------*/
class Farey {
static void Main() {
int n = 10;
Farey1 x = new Farey1(); x.Run(n); Console.ReadLine();
(new Farey2()).Run(n); Console.ReadLine();
(new Farey3()).Run(n); Console.ReadLine();
Console.WriteLine("\n fini");
Console.ReadLine();
} // Main
} // Farey
class Farey1 {
public Farey1() { }
public void Run(int n) {
int d = 0;
int t = 0, m = 1; // PS dau day
do {
Console.Write(t + "/" + m + " ");
++d;
} while (Next(n, ref t, ref m));
Console.WriteLine(" * Farey1: Total " + d + " PS");
}
public bool Next(int n, ref int t, ref int m) {

75

if (t + m == 2) return false;
int a = 1, b = 1, x, y;
for (y = 2; y <= n; ++y) {
x = t * y / m + 1;
if (a * y > b * x) { a = x; b = y; }
}
RutGon(a, b, ref t, ref m);
return true;
}
Console.WriteLine(" * Farey1: Total " + d + " PS");
}
public void Next(int n, ref int t, ref int m) {
int a = 1, b = 1, x, y;
for (y = 2; y <= n; ++y) {
x = t * y / m + 1;
if (a * y > b * x) { a = x; b = y; }
}
RutGon(a, b, ref t, ref m);
}
public int Ucln(int a, int b) {
int r;
while (b != 0) { r = a % b; a = b; b = r; }
return a;
}
public void RutGon(int a, int b, ref int t, ref int m)
{ int d = Ucln(a, b); t = a / d; m = b / d; }
} // Farey1
class Farey2 {
public Farey2() { }
public void Run(int n) {
int mn = 10000;
PS[] a = new PS[mn];
PS[] b = new PS[mn];
int d = 0;
a[d++] = new PS(0, 1); //PS dau day
a[d++] = new PS(1, 1); // PS cuoi day
for (int m = 2; m <= n; ++m) {
int k = 0; b[k++] = a[0];
for (int i = 1; i < d; ++i) {
if (a[i].mau + a[i - 1].mau == m)
b[k++] = new PS(a[i], a[i - 1]);
b[k++] = a[i];
}
d = k; Array.Copy(b, 0, a, 0, d);
}
for (int i = 0; i < d; ++i) a[i].Print();
Console.WriteLine(" * Farey2: Total " + d + " PS");
}
public struct PS {
public int tu, mau;
public PS(int t, int m) { tu = t; mau = m; }
public PS(PS x, PS y)
{ tu = x.tu + y.tu; mau = x.mau + y.mau; }
public void Print()
{ Console.Write(tu + "/" + mau + " ");
}
} // PS
} // Farey2

76

class Farey3 {
public Farey3() { }
public void Run(int n) {
int d = 2;
int t1 = 0, m1 = 1, t2 = 1, m2 = n; // hai PS dau day
int t3, m3, v;
Console.Write(t1 + "/" + m1 + " " + t2 + "/" + m2 + " ");
while (t2 + m2 != 2) {
++d; v = (m1 + n) / m2;
t3 = v * t2 - t1; m3 = v * m2 - m1;
Console.Write(t3 + "/" + m3 + " ");
t1 = t2; m1 = m2; t2 = t3; m2 = m3;
}
Console.WriteLine(" * Farey3: Total " + d + " PS");
}
} // Farey3
} // SangTao2

Bi 2.9 Qy Mi
Minh mun lm mt thip chc tt Qu Mi c nn c to bi 2 n dng, mi dng l mt dy k t
gm n ch ci Q v M sao cho hai dng k nhau khc nhau ti ng mt v tr, dng cui cng cng
c coi l k vi dng u tin. Gi s bn c th gip Minh lm iu . Vi mi gi tr n v k cho trc
bn hy hin th dng th k trong tm thip trn. Cc dng c m s t 1 tr i, 1 n 30.

Thut ton
K hiu T(n) l tm thip c thit k vi gi tr n cho
trc. T(n) dng y s cha 2n dng. T(1) cha hai dng l
Q v M. Gi s ta thit k xong T(n1), khi T(n) s c
thit k theo 3 bc sau.

n = 1
Q
M

n = 2
Q
M

QQ
QM

= 3

QQ
QM
MM
MQ

QQQ
QQM
QMM
QMQ

Bc 1. Lt: Lt T(n1) xung pha di, tc l ly i xng


M MM
qua ng k ngang cui tm thip. Ta k hiu phn i xng ca
Q MQ
T(n1) l T*(n1).
MQ MMQ
Bc 2. Thm Q: Vit thm k t Q vo mi dy ca
MM MMM
T(n1).
QM MQM
Bc 3. Thm M: Vit thm k t M vo mi dy ca
T*(n1).
QQ MQQ
Ta c th vit thm k t vo u hoc cui dy. Trong bi
ny ta chn u dy.
Thit k cc thip T(1), T(2) v T(3)
D dng chng minh rng thut ton trn sinh ra cc tm
thip tha cc yu cu ca u bi. Tht vy, ta gi P l tnh cht Hai dng k nhau khc nhau ti ng
mt v tr. Khi T(1) tha P l hin nhin v n ch cha 2 dng Q v M. Gi s T(n1) tha P. Khi
ng nhin T*(n1) cng tha P. Do php i xng, dng cui cng ca T(n1) v dng u tin ca
T*(n1) ging nhau nn khi thm Q cho dng trn v M cho dng di chng s khc nhau ti v tr
thm . Tng t, dng u tin ca T(n1) v dng cui cng ca T*(n1) ging nhau nn khi thm Q
cho dng u v M cho dng cui chng s khc nhau ti v tr thm.
Da theo thut ton trn ta vit hm Line(n,k) sinh ra dng th k trn tm thip T(n). Th d,
Line(3,7) = MQM. Hm s lp n ln, mi ln sinh 1 k t theo chiu ngc li vi kin thit trn. Ta
thy, nu k > 2n1 th chng t dng k nm trong T*(n1), do k t u dng ca n s phi l M v
dng t T(n1) lt xung dng k s c ch s 2nk+1, ngc li, nu k 2n1 th dng k nm trong T(n1),
do k t u dng ca n l Q.

(*

Pascal

*)

77

function Line(n: integer; k: longint): string;


var s: string; m: longint; i: integer;
begin
m := 1; m := m shl n; { m = 2^n }
for i := n downto 1 do
begin
m := m shr 1; { m div 2 }
if (k <= m) then s := s + Q
else
begin
s := s + M; k := 2*m k + 1;
end;
end;
Line := s;
end;

// C#
static public string Line(int n, int k) {
string s = "";
int m = 1 << n; // m = 2^n
for (int i = n-1; i >= 0; --i) {
m >>= 1;
if (k <= m) s += 'Q';
else { s += 'M'; k = 2*m - k + 1; }
}
return s;
}
phc tp. n.
Ch thch. Kiu int trong C# tng ng vi kiu longint trong Pascal.

M Gray
M Gray ca mt s t nhin k l s (k shr 1) xor k = (k div 2) xor k, trong xor l php ton cng
loi tr theo bt: a xor b = 0 khi v ch khi a = b.
Cc tnh cht ca m Gray
1. M Gray ca hai s t nhin khc nhau th khc nhau: k1 k2 Gray(k1) Gray(k2).
2. M Gray ca hai s t nhin lin tip khc nhau ti ng 1 bit.
3. Gay(0) = 0; Gray(1) = 1;
4. Nu s x c n bit th Gray(2n1) = 2n1.
k
0:
1:
2:
3:
4:
5:
6:
7:

Gray(k)
0000
0001
0010
0011
0100
0101
0110
0111

0:
1:
3:
2:
6:
7:
5:
4:

0000
0001
0011
0010
0110
0111
0101
0100

GLine(4,k)
QQQQ
QQQM
QQMM
QQMQ
QMMQ
QMMM
QMQM
QMQQ

k
8:
9:
10:
11:
12:
13:
14:
15:

Gray(k)
1000
1001
1010
1011
1100
1101
1110
1111

12:
13:
15:
14:
10:
11:
9:
8:

1100
1101
1111
1110
1010
1011
1001
1000

GLine(4,k)
MMQQ
MMQM
MMMM
MMMQ
MQMQ
MQMM
MQQM
MQQQ

M Gray v gi tr ca hm Gline ca 16

78

s t nhin u tin k = 0..15.


Nh m Gray ta c th vit hm GLine(n,k) cho ra dng
k trong thip T(n) mt cch n gin nh sau:
Bc 1. Tnh x = Gray(k) = (k shr 1) xor k = (k div 2)
xor k.
Bc 2. Xt n bit thp ca x, nu l 1 th vit M nu l
0 th vit Q.

(*

Pascal

Frank Gray l nh vt l hc M lm nghin


cu vin ti hng Bell Labs vi hng lot pht
minh c gi tr c ng dng trong truyn
hnh, c hc, in t v ton hc. Nm 1947
Gray ng k bng pht minh v m nh phn
phn hi sau ny c gi l m Gray.

*)

function Gray(k: longint): longint;


begin Gray := (k shr 1) xor k end;
function Gline(n: integer; k: longint): string;
var s: string; i: integer;
const cc: array[0..1] of char = ('Q','M');
begin
k := Gray(k); s = ;
for i := n-1 downto 0 do
s = s + cc[(k shr i) and 1];
GLine := s;
end;

// C#
static public int Gray(int k){ return (k >> 1) ^ k; }
static public string GLine(int n, int k) {
string cc = "QM";
string s = "";
k = Gray(k);
for (int i = n-1; i >= 0; --i)
s += cc[(k >> i) & 1];
return s;
}

Bi 2.10 Tng on
Mt dy con gm cc phn t lin tip nhau trong mt dy cho trc c gi l on. Cho dy
gm N s t nhin. Tm on ngn nht c tng cc phn t bng gi tr K cho trc.
TDOAN.INP

21
0
1
20
11
5

17
2 3
5 5
30 14
0 6 0

TDOAN.OUT

16 3
2 10
6 12
8 0
0

D liu vo: tp vn bn TDOAN.INP


Dng th nht: hai s t nhin N v K,
1 N 2000.
T dng th hai tr i: cc phn t ca dy.
D liu ra: tp vn bn TDOAN.OUT
Cha mt dng duy nht gm hai s t nhin d
ch s u on v L s phn t trong on (chiu
di on). Nu v nghim th ghi 0 0.
Trong cc tp, d liu trn cng dng cch
nhau qua du cch.

Thut ton

79

Ta gii bng k thut ca s trt nh sau. Xt on a[i..j] vi tng S = a[i] + a[i+1] + + a[j], i
j. on ny c gi l ca s. Ta cho ca s ny trt dn qua phi v xt ba tnh hung sau y.
1) (S = K): ta ghi nhn im u i v di on l ji+1. Nu di ny nh hn di LMin th
ta cp nht li cc gi tr iMin v Lmin (th tc Update). Ri tip tc xt ca s mi l a[i+1..j] .
2) (S < K): Ta dch u phi ca ca s t j sang j+1, gi nguyn u tri (th tc Right).
3) (S > K): Ta co u tri ca ca s t i thnh i+1 (th tc Left).
Ta t phn t a[n+1] = 0 lm lnh canh.
(****************************************
TONG DOAN - Doan ngan nhat
co tong K
****************************************)
program TDoan;
uses crt;
const
mn = 2001; bl = #32;
fn = 'TDOAN.INP'; gn = 'TDOAN.OUT';
type mw1 = array[0..mn] of word;
var f,g: text;
n,k: word;
a: mw1;
iMin, LMin: word;
iLeft,iRight: word;
sum: word;
procedure Doc;
var i: word;
begin
assign(f,fn); reset(f); readln(f,n, k);
for i := 1 to n do read(f,a[i]);
close(f);
end;
procedure Left;
begin
sum := sum - a[iLeft]; iLeft := iLeft + 1;
if (iLeft > iRight) then
begin iRight := iLeft; sum := a[iLeft]; end;
end;
procedure Right;
begin iRight := iRight + 1; sum := sum + a[iRight]; end;
procedure Update;
begin
if (LMin > iRight - iLeft + 1) then
begin iMin := iLeft; LMin := iRight - iLeft + 1; end;
Left;
end;
procedure XuLi;
begin
iLeft := 1; iRight := iLeft;
LMin := n + 1; sum := a[1];
repeat
if (sum = k) then Update
else if (sum < k) then Right
else { sum > k } Left;
until (iRight > n);
if (LMin = n+1) then LMin := 0;
end;

80

procedure Ghi;
begin
assign(g,gn); rewrite(g); writeln(g,iMin,bl,LMin); close(g);
end;
BEGIN
Doc; XuLi; ghi;
END.

//

C#

using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class TongDoan {
const string fn = "TDoan.inp";
const string gn = "TDoan.out";
static public int n; // n - so phan tu
static public int k; // Tong can chon
static public int sum; // tong hien co
static public int ileft, iright; // hai dau cua so
static public int imin, lmin;
static public int [] a;
static void Main(string[] args) {
Doc(); XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XemKetQua() {
Console.WriteLine("\n Input: "+fn);
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output: "+gn);
Console.WriteLine(File.ReadAllText(gn));
}
static public void XuLi(){
ileft = 0; iright = ileft;
sum = a[ileft]; lmin = n + 1;
while (iright < n)
if (sum == k) Update();
else if (sum < k) Right();
else /* s > k */ Left();
++imin;
}
static public void Update() {
if (lmin > iright - ileft + 1)
{ imin = ileft; lmin = iright - ileft + 1; }
Left();
}
static public void Left(){
sum -= a[ileft++];
if (ileft > iright)
{ iright = ileft; sum = a[ileft]; }
}
static public void Right() { sum += a[++iright]; }
static public void Doc(){
int[] v =
Array.ConvertAll(((File.ReadAllText(fn))).Split(

81

new char[] { ' ', '\t', '\r', '\n' },


StringSplitOptions.RemoveEmptyEntries),
new Converter<string, int>(int.Parse));
int j = 0; n = v[j++]; k = v[j++];
a = new int[n + 1]; a[n] = 0;
for (int i = 0; i < n; ++i) a[i] = v[j++];
}
static public void Ghi() {
if (lmin == n + 1) File.WriteAllText(gn, "0");
else
File.WriteAllText(gn,imin.ToString()+" "+lmin.ToString());
}
} // TongDoan
} // SangTao2

Bi 2.11 on khng gim di nht


Dijkstra E.
Cho dy gm N s nguyn. Tm on khng gim c chiu di ln nht.
MDOAN.INP

12
1 5 5 1 3
3 3 5 7 9
1 2

MDOAN.OUT

4 7

D liu vo: tp vn bn MDOAN.INP


Dng th nht: s t nhin N,
1 N 20000.
T dng th hai tr i: cc phn t ca dy.
D liu ra: tp vn bn MDOAN.OUT
Cha mt dng duy nht gm hai s t nhin d ch
s u on v L s phn t trong on (chiu di
on).
Trong cc tp, d liu trn cng dng cch nhau qua

du cch.
Th d trn cho ta on khng gim di nht bao gm 7 phn t bt u t phn t th t trong dy
(cc phn t c gch di):
1 5 5 1 3 3 3 5 7 9 1 2

Thut ton
y l bi d, ta c dn cc phn t t input file v so snh hai phn t lin tip nhau l x (phn t
c trc ti bc i) v y (phn t c sau ti bc i+1). Nu y < x th coi nh kt thc mt an khng
gim, ta cp nht ghi nhn li on khng gim di nht. Cc bin tng th trong chng trnh c
dng nh sau:
MaxLen chiu di ca on khng gim di nht hin tm c,
imax - ch s u tin ca on khng gim di nht hin tm c,
ileft ch s u tin ca on khng gim ang xt.
phc tp: c N.

(*

Pascal

*)

(****************************************
MDOAN - Doan tang dai nhat
****************************************)
program MDoan;
uses crt;
const
bl = #32; fn = 'MDOAN.INP'; gn = 'MDOAN.OUT';
var f,g: text;

82

n: integer;
a: mw1;
iLeft, imax: integer;
MaxLen: integer;
procedure Update(i: integer);
begin
if (MaxLen < i - iLeft) then
begin
MaxLen := i - iLeft;
imax := iLeft; ileft := i;
end;
iLeft := i;
end;
procedure XuLi;
var i, x, y: integer;
begin
assign(f,fn); reset(f); readln(f,n);
read(f,x);
iLeft := 1; MaxLen := 0;
for i := 2 to n do
begin
read(f,y);
if (y < x) then Update(i);
x := y;
end;
Update(n+1);
close(f);
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g);
writeln(g,imax,bl,MaxLen);
close(g);
end;
BEGIN
XuLi; ghi;
END.
Trong phng n C# di y ta c ton b d liu vo mt mng a ri x l trn mng ny.

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class DoanKhongGiam {
const string fn = "MDoan.inp";
const string gn = "MDoan.out";
static public int n; // n - so phan tu
static public int imax; // chi so dau cua doan max
static public int ileft; // chi so dau cua doan dang xet
static public int maxlen; // chieu dai max
static public int [] a;
static void Main(string[] args) {
Doc(); XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();

83

}
static public void XemKetQua(): t vit
static public void XuLi() {
ileft = 0; maxlen = 0;
for (int i = 1; i < n; ++i)
if (a[i] < a[i-1]) Update(i);
Update(n);
}
static public void Update(int i) {
if (maxlen < i - ileft)
{ maxlen = i - ileft; imax = ileft; ileft = i; }
}
static public void Doc(): t vit
static public void Ghi() {
File.WriteAllText(gn, imax.ToString() + " " +
maxlen.ToString()); }
} // DoanKhongGiam
} // SangTao2

Bi 2.12 on n iu di nht
Dijkstra E.
Cho dy gm N s nguyn. Tm on n iu (khng gim hoc khng tng) c chiu di ln nht.
DONDIEU.INP

12
1 5 5 1 3
3 3 5 7 9
1 2

DONDIEU.OUT

4 7

D liu vo: tp vn bn DONDIEU.INP


Dng th nht: s t nhin N,
1 N 20000.
T dng th hai tr i: cc phn t ca dy.
D liu ra: tp vn bn DONDIEU.OUT
Cha mt dng duy nht gm hai s t nhin d ch
s u on v L s phn t trong on (chiu di
on).
Trong cc tp, d liu trn cng dng cch nhau qua

du cch.

Thut ton
Edsger Wybe Dijkstra (1930-2002)
Sinh nm 1930 ti Rotterdam, Holland.
1948-1956 hc Ton v Vt l l thuyt
ti i hc Leyden. 1952-1962 nghin
cu ti Trung tm Ton hc Amsterdam.
1962-1973 Gio s Ton ti i hc Bch
khoa Eindhoven, Holland v i hc
Texas Austin. Dijkstra l mt trong nhng
ngi i tin phong trong lnh vc lp
trnh, ngi khi xng v t nn mng
cho nguyn l lp trnh cu trc.

84

Edsger Wybe Dijkstra


(photo 2002 Hamilton
Richards)

Nhn xt:
on c 1 phn t l on n iu (tng, gim),
on gm mt dy lin tip cc phn t bng nhau l on n iu (tng, gim).
Ta dng hai bin m cc phn t tng hoc bng nhau lin tip, dt v m cc phn t gim hoc
bng nhau lin tip, dg. Nu ai = ai1 ta tng ng thi dt v dg 1 n v. Nu ai > ai1 ta tng dt thm 1 n
v v t li dg = 1. Nu ai < ai1 ta tng dg thm 1 n v v chnh li dt = 1. Sau mi bc ta cp nht on
n iu di nht tm c. Chng trnh Pascal c v x l trc tip file input, chng trnh C# c ton
b d liu vo mng ri x l trn mng.
phc tp: c N.
Cc bin tng th:
n: s lng phn t,
dt: m s phn t trong dy tng,
dg: m s phn t trong dy gim.
iMax: ch s u ca on n iu di nht,
MaxLen: chiu di (s phn t) ca on n iu di nht.

(*

Pascal

*)

program DonDieu;
uses crt;
const
bl = #32; fn = 'DONDIEU.INP'; gn = 'DONDIEU.OUT';
var f,g: text;
n: integer;
dt,dg: integer;
iMax, MaxLen: integer;
function Max(a,b,c: integer): integer;
begin
if (a < b) then a := b; { a = Max(a,b) }
if (a > c) then Max := a
else Max := c;
end;
procedure XuLi;
var i,m,x,y: integer;
begin
assign(f,fn); reset(f);
readln(f,n); read(f,x);
dt := 1; dg := 1;
MaxLen := 1; iMax := 1;
for i := 2 to n do
begin
read(f,y);
if (y = x) then
begin dt := dt + 1; dg := dg + 1; end
else if (y > x) then
begin dt := dt + 1; dg := 1; end
else { y < x }
begin dg := dg + 1; dt := 1; end;

85

m := Max(MaxLen, dt, dg);


if (m > MaxLen) then
begin MaxLen := m; iMax := i - MaxLen + 1;
x := y;
end;
close(f);
end;
procedure Ghi;
begin
assign(g,gn); rewrite(g);
writeln(g, iMax, bl, MaxLen); close(g);
end;
BEGIN
XuLi; Ghi;
END.

end;

// C#
using System;
using System.IO;
using System.Collections;
namespace SangTao2 {
class DonDieu {
const string fn = "DonDieu.inp";
const string gn = "DonDieu.out";
static public int n; // n - so phan tu
static public int imax; // chi so dau tien cua doan max
static public int maxlen; // chieu dai max
static public int [] a;
static void Main(string[] args) {
Doc(); XuLi(); Ghi(); XemKetQua();
Console.WriteLine("\n Fini ");
Console.ReadLine();
}
static public void XemKetQua(): t vit
static public void XuLi(){
imax = 0; maxlen = 1;
int dt = 1, dg = 1;
int m;
for (int i = 1; i < n; ++i){
if (a[i] == a[i - 1]) { ++dt; ++dg; }
else if (a[i] < a[i - 1]) { dt = 1; ++dg; }
else /* a[i] > a[i-1] */ { ++dt; dg = 1; }
m = Max(maxlen, dt, dg);
if (maxlen < m)
{ maxlen = m; imax = i - maxlen + 1; }
}
}
static public int Max(int a, int b, int c){
if (a < b) a = b; // a = Max(a,b)
return (a > c) ? a : c;
}
static public void Doc(): t vit
static public void Ghi(): t vit
} // DonDieu
} // SangTao2

86

Bi 2.13 Ly tha 2, 3 v 5
Dijkstra E.
Vi mi gi tr N cho trc hy sinh N s u tin theo trt t tng dn l tch cc ly tha ca 2, 3
v 5.
LUYTHUA.INP

LUYTHUA.OUT

D liu vo: tp vn bn LUYTHUA.INP


Cha s t nhin N, 1 N 1000.
D liu ra: tp vn bn LUYTHUA.OUT

12

1
2
3
4
5
6
8
9
10
12
15
16

N s tm c, mi dng mt s.

Thut ton
Gi S l tp cc s cn tm. Ta c
(i) 1 S
(ii) Nu x S th 2x, 3x, 5x S.
Gi s cc phn t trong S c sp tng v ta
tm c phn t th i. Ta k hiu S(i) = { a1, a2,,ai }.
tm phn t th i+1 ta nhn xt
ai+1 = Min { 2x, 3y, 5z | x, y, z S(i), 2x > ai, 3y >
ai, 5z > ai }
Ta s dng 3 bin i2, i3, i5 ghi nhn cc ch s
trong S sao cho ai2 = x, ai3 = y v ai5 = z. Cc bin a[1], i2,
i3 v i5 c khi tr 1.

Khi hm Next(i) sinh phn t st sau phn t A[i] s nh sau:


function Next(i: integer): integer;
begin
while (a[i2] * 2 <= a[i]) do i2 := i2 + 1;
while (a[i3] * 3 <= a[i]) do i3 := i3 + 1;
while (a[i5] * 5 <= a[i]) do i5 := i5 + 1;
Next := Min(a[i2]*2, a[i3]*3, a[i5]*5);
end;

(*

Pascal

*)

(***************************************
LUY THUA cua 2, 3, 5
*************************************)
program LuyThua;
uses crt;
const bl = #32; mn = 1001; fn = 'LUYTHUA.INP'; gn = 'LUYTHUA.OUT';
type ml1 = array[0..mn] of longint;
var f,g: text;
n: integer;
a: ml1;
procedure Doc: t vit;
function Min(a,b,c: longint): t vit;
function Next(i: integer): t vit;
procedure Sinh;
var i: longint;
begin
assign(g,gn); rewrite(g);

87

a[1] := 1; writeln(g,1);
i2 := 1; i3 := 1; i5 := 1;
for i := 2 to n do
begin
a[i] := Next(i-1);
writeln(g,a[i]);
end;
close(g);
end;
BEGIN
Doc; Sinh;
END.

//

C#

using System;
using System.IO;
namespace SangTao2 {
/*-------------------------------------------*
Luy thua 2, 3, 5
* ------------------------------------------*/
class LuyThua235 {
const string fn = "LuyThua.inp";
const string gn = "LuyThua.out";
static public int n; // so luong phan tu
static public int[] a;
static void Main(){
Doc(); Sinh(); Ghi(); XemKetQua();
Console.WriteLine("\n fini");
Console.ReadLine();
} // Main
static public void Doc()
{ n = int.Parse(File.ReadAllText(fn).Trim()); }
static public void Sinh(){
a = new int[n];
int i2 = 0, i3 = 0, i5 = 0; a[0] = 1;
int n1 = n-1;
for (int i = 0; i < n1; ++i){ // Next
while (a[i2] * 2 <= a[i]) ++i2;
while (a[i3] * 3 <= a[i]) ++i3;
while (a[i5] * 5 <= a[i]) ++i5;
a[i + 1] = Min(a[i2] * 2, a[i3] * 3, a[i5] * 5);
}
}
static public int Min(int x, int y, int z) : t vit
static public void Ghi(){
StreamWriter g = new StreamWriter(gn);
for (int i = 0; i < n; ++i) g.WriteLine(a[i]);
g.Close();
}
static void XemKetQua(): t vit
} // LuyThua235
} // space

88

C h ng 3
T r ch i

Cc bi ton tr chi kh a dng v thng l kh.


Chng ta xt loi tr chi th nht vi cc ga thit sau y:
1. Tr chi gm hai u th l A v B, lun phin nhau, mi ngi i mt nc. Ta lun gi thit
u th i trc l A.
2. Hai u th u chi rt gii, ngha l c kh nng tnh trc mi nc i.
3. u th no n lt mnh khng th i c na th chu thua v vn chi kt thc.
4. Khng c th ha, sau hu hn nc i s xc nh c ai thng, ai thua.
Gi thit chi gii nhm trnh cc trng hp n may, tc l cc trng hp do i phng h
hnh m i lc nc. iu ny tng ng vi gi thit c hai u th u c th tnh trc mi nc i
(vi loi tr chi hu hn) hoc c hai u th u bit cch i tt nht. tin trnh by chng ta gi cc
tr chi loi ny l chi c, mi th ca bn c l mt tnh hung vi d liu c th, ta thng gi l mt
cu hnh.
Cc bi ton tin lin quan n loi tr chi ny thng l:

Lp trnh xc nh vi mt th c cho trc th ngi i trc (u th A) s thng hay thua.

Lp trnh my tnh chi vi ngi. D nhin chng trnh bn lp ra l dnh cho my tnh.

Lp trnh hai my tnh chi vi nhau.


Vi loi tr chi ny c mt heuristic mang tnh ch o sau y:
Trc ht cn xc nh c mt tnh cht T tha cc iu kin sau y:
a) Th thua cui cng tha T,
b) Mi nc i lun lun bin T thnh V = not T,
c) Tn ti mt nc i bin V thnh T.
Tnh cht T c gi l bt bin thua ca tr chi.

Vic chuyn th X thnh not X thng c gi l lt th X. Cc qui tc a - c c th pht biu li


nh sau:

89

T c gi l bt bin thua nu

u th no c cch y u th khc vo th
thua T th u th s thng.

a') Th thua cui cng tha T,


b') Mi nc i t T u lt T thnh V,
c') Tn ti mt nc i lt V thnh T.

u th no khng th y u th khc vo th
thua T th u th s thua.

Nc i y c hiu l nc i hp l tc l nc i tun th cc qui nh ca tr chi, th d


"xe lin, pho cch" trong c tng qui nh rng qun xe c th "n" trc tip cc qun ca i phng
nm trn ng i ca n, cn qun pho th phi "n" qua mt qun m.
im kh nht ca loi ton ny l xc nh bt bin thua.

Bi 3.1. Bc si A
Trn bn c mt ng si N vin, hai u th A v B ln lt i, A i nc u tin. Mi nc i
u th buc phi bc t 1 n M vin si khi bn. u th no n lt mnh khng i ni th thua. C
hai u th u chi rt gii. Vi hai s N v M cho trc hy cho bit A thng (ghi 1) hay thua (ghi 0).
Ta th chi vi M = 3 v vi d liu ban u N = 1, 2 , tnh nc i cho u th A bn hy k
mt bng gm 2 dng. Dng th nht l cc gi tr ca N. Dng th hai c ghi 0 ng vi tnh hung A
thua v 1 cho tnh cho trng hp A thng, nu A l u th i nc u tin.
M = 3

N =

0 1 2 3 4 5 6 7 8 9 10 11 12 13

A thng (1) hay thua (0)?

0 1 1 1 0 1 1 1 0 1 1

Cch i: s vin cn bc chc thng

# 1 2 3 # 1 2 3 # 1 2

Mt vi tnh hung cho bi Bc si A, M = 3; # - u hng/bc tm 1 vin


Th d, vi M = 3 cho trc v c nh, A l u th i trc, ta c
N = 0 l mt th thua, v A khng c cch i.
N = 1 l mt th thng, v A s bc 1 vin, B ht cch i.
N = 2 l mt th thng, v A s bc 2 vin, B ht cch i.
N = 3 l mt th thng v A s bc 3 vin, B ht cch i.
N = 4 l mt th thua, v d A bc 1, 2, hoc 3 vin u dn n cc th thng l 3, 2, 1
Lm th no xc nh c bt bin ca tr chi? Phng php n gin l t duy Nhn - Qu
hay l lp lun li. C th l, nu bit kt qu l Q ta hy gng tm nguyn nhn N sinh ra Q. Ta rng,

Qui tc xc nh th thng / thua


T mt th X ang xt,

nu tm c mt nc i dn n th thua T th X s l th thng V, v

nu mi nc i t X u dn n th thng th X s l th thua T.

Trc ht ta s tm mt th thua nh nht ca cuc chi hay cn gi l th thua kt hoc th thua


cui cng, v u th no gp th ny u phi u hng v vn chi kt thc.
D thy th thua kt s l N = 0: Ht si, khng th thc hin c nc i no.

90

Vy trc , nhng nc i no c th dn n th thua T(N = 0)?


Do mi u th ch c php bc 1, 2 hoc 3 vin nn cc th thng V trc ch c th l N = 1,
2, hoc 3. Ta vit
T(N = 0) V(N = 1 | 2 | 3) T(N = ?)
trong T l k hiu cho th thua, V l k hiu cho th thng.
Ta th xc nh th thua T(N = ?). D thy vi N = 4 th mi cch bc 1, 2 hoc 3 vin si u dn
n th thng V(N = 3 | 2 | 1). Ta c,
T(N = 0) V(N = 1 | 2 | 3) T(N = 4)
n y ta c th d on bt bin thua s l N = 4k, cho trng hp M = 3, hoc tng qut hn, N
= k(M+1), k 0.
Vy bt bin thua l:
T: S vin si trong ng l bi ca M+1: N = k(M+1), k 0.
Ta s chng minh rng nu N = k(M+1), k = 0, 1, 2,th ngi i trc (l A) lun lun thua.
Trc ht rng nu u th A gp s si l bi ca M+1 th vi mi cch i ca A s si cn li
s khng phi l bi ca M+1. Tht vy, mun bo ton tnh cht l bi ca M+1 th A buc phi bc mt
bi no ca M+1, y l iu khng c php v vi phm lut chi.
Gi s N = k(M+1), k 1. Gi s si A bc l s. Ta c, do 1 s M nn B s bc u = (M+1)s
vin si v do s si cn li s li l N = k(M+1) s ((M+1) s) k(M+1)(M+1) = (k1)(M+1). y
l mt bi ca (M+1).
Nu s si l bi ca M+1 th vi mi cch i hp l, s si cn li s khng cn l bi ca M+1.
Nu s si khng phi l bi ca M+1 th lun lun tn ti mt cch i chnh s si tr thnh bi ca
M+1.
Kt lun Bi Bc si A
Nu s si N = k(M+1), k 0
th u th no i trc s thua.

Vi gi thit A l u th i trc, ta vit hm Ket(N,M) cho ra gi tr 1 nu A thng, ngc li


hm cho gi tr 0 nu A thua. Hm c hai tham bin: N l s vin si trong ng, M l gii hn s vin si
c php bc. Hm n thun ch kim tra xem tr N c l bi ca M+1 hay khng.
(* Pascal *)
function Ket(N,M: integer): integer;
begin
if (N mod (M+1) = 0) then ket := 0 else Ket := 1;
end;
Hm CachDi(N,M) di y m nhn chc nng hng dn ngi chi chn mt cch i. Trc
ht cn kim tra xem th ang xt l thng hay thua. Nu l th thua v cn si th bc 1 vin nhm ko
di thi gian thua. Nu l th thng th bc s si d s si cn li s l bi ca (M+1).
(* Pascal *)
function CachDi(N,M: integer): integer;
var r: integer;
begin
r := N mod (M+1);
if r = 0 then { thua }
begin
if N = 0 then CachDi := 0 else CachDi := 1;
exit;
end;

91

CachDi := r;
end;

// C#
static int Ket(int n, int m) { return (n%(m+1) == 0) ? 0 : 1;}
static int CachDi(int n, int m) {
int r = n % (m+1);
if (r == 0) // thua
return (n == 0) ? 0 : 1;
return r;
}

Bi 3.2. Bc si B
Cho ng si N vin, hai u th A v B ln lt i, A i nc u tin. Mi nc i u th c
php bc t 1 n M vin si. u th no thc hin nc i cui cng th thua. C hai u th u chi
rt gii. Vi hai s N v M cho trc hy cho bit A thng (ghi 1) hay thua (ghi 0).
Ta nhn thy bi ny ch khc bi Bc si A iu kin thua: ai bc qun cui cng s thua.
Chc chn l bn s c th xc nh ngay c bt bin thua ca tr chi ny l
N = k(M+1) + 1, k 0. Tuy nhin, hnh thnh k nng pht hin lut chi cho cc bi ton kh hn sau
ny, bn hy gng thc hin cc bc tm kim theo cc s sau y:
S 1: Th vi vi d liu ban u: M = 3; N = 1, 2,
M = 3

N =

1 2 3 4 5 6 7 8 9 10 11 12 13

A thng (1) hay thua (0)?

0 1 1 1 0 1 1 1 0 1

Cch i: s vin cn bc

# 1 2 3 # 1 2 3 # 1

chc thng.
Mt vi tnh hung cho bi Bc si B, M = 3; # - u hng/bc tm 1 vin
S 2: Tnh hai hai th thua lin tip theo lp lun li (Nhn - qu).
S tnh hai th thua lin tip
Bc 1 Xc nh th thua nh nht: T (N = 1)
Bc 2 Xc nh cc th thng V dn n T: T V c mt nc i dn n T.
T(N=1) V(N = 2 | 3 | 4)
Bc 3 Xc nh th thua T dn n V: Mi cch i t T u ri vo V.
T(N=1) V(N = 2 | 3 | 4) T(N=5)
Bc 4 Tng qut ha, xy dng v chng minh cng thc xc nh bt bin thua:
N = k(M+1)+1, k 0

S 3: Tng qut ha (Chi tit ha Bc 4 trong S 2). Trong s 3 di y ta k hiu X(k)


l s vin si ti th X xt trong bc k = 0, 1, 2... X c th l th thng V hoc th thua T, ch rng bc
k c xt theo qu trnh lp lun li ch khng xt theo din tin ca tr chi.

92

Bc 4. Tng qut ha
Bc 4.1

Th thua nh nht: T(0) = 1.

Bc 4.2

Gi thit th thua ti bc k l T(k) (s vin si ngi i trc thua).

Bc 4.3

Xc nh cc th thng V(k) dn n T(k): C mt cch i trn bn cn T(k) vin si.


T(k) V(k) = T(k) + d; 1 d M.

Bc 4.4

Xc nh th thua T(k+1) dn n V(k): Mi cch i t T(k+1) u ri vo V(k) = T(k) + d;


1 d M:
T(k) V(k) = T(k) + d; 1 d M T(k+1) = Max {V(k)}+1 = T(k)+(M+1)

Bc 4.5

Chng minh cng thc T(k) bng qui np: T(k) = k(M+1)+1
D on cng thc: Ta c, theo cng thc thu c Bc 4.4, T(k+1) = T(k)+(M+1),
T(0) = 1;
T(1) = T(0)+(M+1) = 1+(M+1);
T(2) = T(1)+(M+1) = 1+(M+1)+(M+1) = 2(M+1)+1;
T(3) = T(2)+(M+1) = 2(M+1)+1+(M+1) = 3(M+1)+1;
...
D on: T(k) = k(M+1)+1.

Chng mnh bt bin thua: Nu s si trong ng l T(k) = k(M+1)+1, k 0 th ai i trc s thua.


C s qui np: vi k = 0 ta c T(0) = 0.(M+1)+1 = 1. y l th thua nh nht.
Gi s vi k 1 ta c th thua l T(k) = k(M+1)+1. Ta chng minh rng T(k+1) = (k+1)(M+1)+1 s
l th thua tip theo v gia hai th thua ny l cc th thng. Tht vy, v T(k) l th thua nn cc th c
dng V(k) = T(k)+d, 1 d M s u l th thng. T y suy ra th thua tip sau phi l T(k+1) =
T(k)+M+1 = k(M+1)+1+(M+1) = (k+1)(M+1)+1.

Kt lun Bi Bc si B
Nu s si N = k(M+1)+1, k 0
th u th no i trc s thua.

Ta cng c th s dng hm f(N) xc nh xem vi ng si c N vin th ngi i trc s thng


(f(N) = 1) hay thua (f(N) = 0). Ta c, f(1) = 0 v vi 1 vin si th ai bc vin s thua. Gi s f(N) = 0.
D thy, khi f(N+d) = 1 vi 1 d M, v ch cn bc d vin si l dn n th thua. Tip n
f(N+(M+1)) = 0 v vi mi cch bc s vin si, 1 s M i phng s bc tip u = (M+1)s s si
cn li l N vin ng vi th thua. T suy ra f(N) = 0 vi N = k(M+1)+1; cn li l f(N) = 1.
Hai hm Ket(N,M) v CachDi(N,M) vi N > 0 khi s nh sau.
(* Pascal *)
function Ket(N,M: integer): integer; {0: thua; 1: thang}
begin
if (N mod (M+1) = 1) then ket := 0 else Ket := 1;
end;
function CachDi(N,M: integer): integer;
var r: integer;
begin
r := N mod (M+1);
if (r = 1) then { thua: boc tam 1 vien }

93

CachDi := 1 else
if (r = 0)then CachDi := M
else CachDi := r-1;
end;

// C#
static int Ket(int n, int m)// 0: thua; 1: thang
{ return (n % (m+1) == 1) ? 0 : 1; }
static int CachDi(int n, int m) {
int r = n % (m+1);
if (r == 1) // thua, boc tam 1 vien
return 1;
else return (r == 0) ? m : r-1;
}

Bi 3.3. Bc si C
Cho ng si N vin, hai u th A v B ln lt i, A i nc u tin. Ti mi nc i, u th
buc phi bc ti thiu 1 qun, ti a na s qun trong ng. u th no n lt mnh khng i ni th
thua. C hai u th u chi rt gii. Cho bit A thng hay thua.
Ch :
Nu s qun l th bc na non,
ng no cn 1 qun th khng c cch bc ng , v 1 div 2 = 0 trong khi yu cu ca
lut chi l phi bc ti thiu 1 qun.
S 1:
Th vi vi d liu ban u: N = 1, 2, 3,
N

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

A thng (1) hay thua (0)? 0 1 0 1 1 1 0 1 1 1

# 1 # 1 2 3 # 1 2 3

Cch i: s si cn bc
chc thng

Mt vi tnh hung cho bi Bc si C; # - u hng/bc tm 1 vin.

S 2: Kho st hai th thua lin tip theo lp lun li (Nhn - qu).


S tnh hai th thua lin tip
Bc 1 Xc nh th thua nh nht: T (N = 1)
Bc 2 Xc nh cc th thng V dn n T: T V c mt nc i dn n T.
T(N = 1) V(N = 2)
Bc 3 Xc nh th thua T dn n V: Mi cch i t T u ri vo V.
T(N = 1) V(N = 2) T(N = 3)
Bc 4 Tng qut ha, xy dng v chng minh cng thc xc nh bt bin thua:
N = 2k 1, k 1

94

S 3: Tng qut ha (Chi tit ha Bc 4 trong S 2). Trong s 3 di y ta k hiu X(k)


l s vin si ti th X xt trong bc k = 0, 1, 2, theo lp lun li t th thua nh nht tr i. X c th l
th thng V hoc th thua T.
Bc 4. Tng qut ha
Bc 4.1

Th thua nh nht: T(0) = 1.

Bc 4.2

Gi thit th thua T(k) c N vin si: T(k) = N.

Bc 4.3

Xc nh cc th thng V(k) dn n T(k): C mt cch i trn bn cn N vin si.


T(k) V(k) = N + d; 1 d N.

Bc 4.4

Xc nh th thua T(k+1) dn n V(k): Mi cch i t T(k+1) u ri vo V(k) = N + d;


1 d N.
T(k) V(k) = N + d; 1 d N T(k+1) = Max {V(k)} + 1 = N+N+1

Bc 4.5

Chng minh cng thc T(k) bng qui np: T(k) = 2 k1.

Gi T(k) l th thua kho st ti bc th k. Ta c,


Th thua nh nht T(0) = 1: nu c 1 vin si th khng i ni: chu thua.
Gi s th thua ti bc th k l T(k) = N
Khi cc th thng dn n th T(k), theo lut chi s l V(k) = T(k)+d,
1 d T(k) v th thua tip sau phi l T(k+1) = T(k)+T(k)+1 = 2T(k)+1.
Tng hp li ta c
T(0) = 1,
T(1) = 2T(0)+1 = 2+1,
T(2) = 2T(1)+1 = 2(2+1) + 1 = 22+2+1,
T(3) = 2T(2)+1 = 2(22+2+1)+1 = 23+22+2+1.
...
p dng cng thc ak+1 1= (ak + ak-1+...+a+1) (a1) ta d on:
T(k) = 2k + 2k-1+...+2+1 = (2k+1 1)/(21) = 2k+1 1.
Ta dng qui np ton hc chng minh rng T(k) = 2 k+1 1.
Vi k = 0, ta c T(0) = 21 1 = 2 1 = 1. Vy T(k) ng vi k = 0.
Gi s T(k) =

2k+1 1. Ta chng minh T(k+1) = 2k+2 1.

Ta c, T(k+1) = 2T(k)+1 = 2(2k+11)+1 = 2k+22+1 = 2k+21, pcm.

Kt lun Bi Bc si C
Nu s si N c dng 2k - 1, k 1 th u
th no i trc s thua.

Cc s dng 2k 1 c gi l s Mersenne mang tn nh ton hc Php th k th XVII, ngi


u tin nghin cu chng.

95

Vi gi thit A l u th i trc, ta vit hm Ket(N) cho ra gi tr 1 nu A thng, ngc li hm


cho gi tr 0 nu A thua. Hm ch n thun kim tra xem N c phi l s Mersenne hay khng. Nu ng
nh vy th u th A s thua, ngc li l A thng.

Marin Mersenne (1588-1648) l con mt gia nh nng


dn Php. Lc u ng hc thn hc v trit hc, sau
chuyn sang nghin cu ton hc v m nhc. ng
li nhng kt qu l th v c s ton hc ca m
nhc, hnh hc v l thuyt s.

Ta rng N = 2k1 tng ng vi N+1 = 2k. V cc s nguyn trong my tnh u c biu


din di dng nh phn, nn tnh gi tr 2k ta ch vic dch s 1 qua tri k bit.
(* Pascal *)
function Ket(N : integer) : integer;
var m,n1: integer;
begin
n1 := N + 1; m := 1;
while (m < n1) do m := m shl 1;
{ m = 2k n1 = N+1 ==> N 2k-1 }
if m = n1 then Ket := 0 else Ket := 1;
end;
Hm CachDi di y s xc nh s si cn bc cho mi tnh hung. Trc ht hm kim tra xem
s si trong ng c phi l s Mersenne hay khng qua h thc N+1 = 2 k ? Nu N = 2k 1 th ngi no i
s thua, do ta chn cch i chm thua nht bng vic bc 1 vin si. D nhin nu N = 1 th ta phi chu
thua bng cch gn CachDi = 0. Ta xt trng hp N khng phi l s Mersenne. Khi tn ti mt s
nguyn k tha 2k 1 < N < 2k+1 1. Ta cn bc bt s si chnh lch l s = N(2k 1) s si cn li c
dng 2k 1. Ta chng minh 1 s N/2, tc l cch i ny l hp l theo quy nh ca u bi. Tht vy,
do 2k 1 < N nn s = N(2k 1) 1. Mt khc, nu s > N/2 tc l N(2k1) > N/2 th N/2 > 2k1 hay N >
2k+12. T y suy ra N 2k+11 mu thun vi iu kin ca k. Vy ta phi c s N/2.
(* Pascal *)
function CachDi(N : integer) : integer;
var m, n1: integer;
begin
n1 := N + 1; m := 1;
while (m < n1) do m := m shl 1;
{ m = 2k n1 = N+1 ==> N 2k-1 }

96

if m = n1 then { N = 2k - 1: Thua }
begin
if N = 1 then CachDi := 0
else CachDi := 1;
exit;
end;
{ m = 2k > N+1 }
m := m shr 1;
{ m = 2k-1 < N+1 < 2k = 2m ==> m-1 < N < 2m-1 }
CachDi := N-m+1;
end;

// C#
static int Ket(int n) {
int m = 1,n1 = n + 1;
while (m < n1) m <<= 1;
// m = 2k n1 = n+1 ==> n 2k-1
Ket = (m == n1) ? 0 : 1;
}
static int CachDi(int n) {
int m = 1, n1 = n + 1;
while (m < n1) m <<= 1;
// m = 2k n1 = n+1 ==> n 2k-1
if (m == n1) // Thua
return (n == 1) ? 0 : 1;
// m = 2k > n+1
m >>= 1;
// m = 2k-1 < n+1 < 2k = 2m ==> m-1 < n < 2m-1
return n-m+1;
}

Bi 3.4. Chia on
Dng pht biu khc ca Bi Bc si C
Cho mt on thng trn trc s di N n v vi cc im chia nguyn. Hai bn ln lt thc hin
thao tc sau y: Ct on thng ti mt im nguyn nm trong on thu c 2 on con sau vt
i on ngn, trao on di cho ngi kia. Nu hai on bng nhau th vt i mt on ty . Bn no n
lt mnh khng th thc hin c thao tc trn th thua. Hy cho bit bn i trc thng hay thua. Gi
thit rng hai bn u chi rt gii.

Bi 3.5. Bc si D
Cho 2 ng si vi s vin si ln lt l N v M vin. Hai ngi chi A v B, A lun i trc. Lt
chi: Chn ng ty , bc ti thiu 1 vin v ti a c ng. u th no n lt mnh m khng i ni
th thua. Hy cho bit A thng hay thua. Gi thit rng hai u th u chi rt gii.
Thut ton
Bi ny kh d gii.
Bt bin thua cho Bi Bc si
D
S si ca hai ng bng nhau.

97

Nu s si ca hai ng khc nhau th A l u th i trc s cn bng hai ng bng cch chn


ng ln ri bc bt s si chnh lch s si ca hai ng tr thnh bng nhau. Khi B i th s bin hai
ng thnh khc nhau, n lt A li cn bng hai ng
Ta cng d dng vit c hm kt nh sau:
(* Pascal *)
function Ket(N,M : integer) : integer;
begin
if N = M then Ket := 0 else Ket := 1;
end;
Th tc CachDi di y s xc nh ng v s si cn bc cho mi tnh hung. Hm nhn vo l
N - s lng si ca ng th nht v M - s lng si ca ng th hai v cho ra hai gi tr: D - ng si
cn chn v S - s vin si cn bc ti ng . Nu N = M, tc l gp th thua th nh bc 1 vin ti ng
ty chn, mt cch ngu nhin. Ta qui c D = 0 l tnh hung chu thua, tc l khi c hai ng ht si.
(* Pascal *)
procedure CachDi(N, M : integer; var D,S : integer);
{ Dong 1: N vien, Dong 2: M vien soi }
begin
if N = M then { Se Thua }
begin
if N = 0 then D := 0 { Het soi: dau hang }
else
begin { Keo dai cuoc choi }
S := 1; { boc 1 vien }
D := random(2)+1;{tai 1 dong tuy chon}
end;
exit;
end;
{ Tinh huong thang }
if N > M then D := 1 else D := 2; { Chon dong nhieu soi }
S := abs(N-M); { Boc so soi chenh lech }
end;

// C#
static int Ket(int n, int m) {
// ng 1: n vin; ng 2: m vin
return (n == m) ? 0 : 1;
}
static void CachDi(int n, int m, out int s, out int d) {
Random r = new Random();
if (n == m) { // thua
if (n == 0) d = 0;
else {
s = 1;
d = r.Next(2) + 1;
}
}
// n != m: thang
d = (n > m) ? 1 : 2;
s = (d == 1) ? (n m) : (m n);
}
Bn th ngh
Tnh hnh s ra sao nu ta xt li bi ny vi iu kin thu nh sau: u th bc nhng qun cui
cng cn trn bn s thua?

98

Bi 3.6. Bc si E
Cho 2 ng si vi s vin si ln lt l N v M vin. Hai ngi chi A v B, A lun i trc. Lt
chi: Chn ng ty , bc ti thiu 1 vin v ti a c ng. u th no bc nhng qun cui cng cn
trn bn s thua. Hy cho bit A thng hay thua. Gi thit rng hai u th u chi rt gii.
Thut ton
D thy khi mt trong hai ng ch cn 1 vin si, ng th hai c si th ai i trc s thng, v
ngi ch vic bc ht ng si cn li. Ta xt trng hp N, M > 1. Vi trng hp ny ta s dng bt
bin thua T(N=M) v tm cch cn bng hai ng si.
M

Gi A l u th i trc, ta k hiu f(N,M) l hm hai bin cho gi tr 1 nu A thng, v gi tr 0


nu A thua, N v M l s si trong hai ng. D thy f l hm i xng, tc l f(N,M) = f(M,N) v trt t
ca hai ng si khng quan trng. tnh tr ca f ta s dng ma trn hai chiu f, cc dng ng vi gi tr
N, cc ct ng vi gi tr M. Ma trn ny i xng qua ng cho chnh, do ta lun gi thit l N M
v s ln lt in tr theo cc dng, ti mi dng N ta bt u in tr t cc ct M N tr i. Ta c nhn
xt th v sau y:
* f(1,0) = f(0,1) = f(N,N) = 0, N > 1,
* Cc gi tr cn li trong bng u bng 1.
Hm Ket v th tc CachDi s nh sau.
Bt bin thua cho bi Bc si
E
1. N = M > 1, hoc
2. (0, 1), (1, 0)
function Ket(N,M : integer) : integer;
begin
if (N + M = 1) or ((N = M) and (N > 1))
then Ket := 0 else Ket := 1;
end;
Vi th tc CachDi cho tnh hung thng ta phi xt kh nhiu trng hp.
Trng hp 1. Ch cn mt ng: ta bc ng kia, bt li mt vin.
Trng hp 2. C mt ng cha duy nht 1 vin si: ta bc ht ng kia.
Hai trng hp 1 v 2 c th gp lm 1 nh sau:
Trng hp 1&2. Nu mt ng cn khng qu 1 vin si th bc ng kia s si N+M 1.
Trng hp 3. Cn bng s si hai ng bng cch bc s si chnh lch.

99

rng trong c 3 trng hp thng v c trng hp thua ta u chn ng c nhiu si hn


bc.
procedure CachDi(N,M : integer; var D,S : integer);
begin
{ Chon dong nhieu soi }
if N > M then D := 1 else D := 2;
if (N + M = 1) or ((N = M) and (N > 1))then
begin { Se Thua }
S := 1; { boc 1 vien }
exit;
end;
{ Cac tinh huong thang }
if (N < 2) or (M < 2) then S := N+M-1
else S := abs(N-M);
end;

// C#
static int Ket(int n, int m) {
return (n + m == 1 || (n == m && n > 1)) ? 0 : 1;
}
static void CachDi(int n, int m, out int d, out int s) {
d = (n > m) ? 1 : 2;
if (n + m == 1 || (n == m && n > 1)) { // se thua
s = 1; // boc 1 vien
return;
}
s = (n < 2 || m < 2) ? (n+m-1) : Math.Abs(n - m);
}

Bi 3.7. Bc si F
Cho 2 ng si vi s vin si ln lt l N v M vin, N, M > 1. Hai ngi chi A v B, A lun i
trc. Lt chi: Chn ng ty , bc ti thiu 1 vin v ti a na s vin ca ng. u th no n
lt mnh m khng i ni th thua. Hy cho bit A thng hay thua. Gi thit rng hai u th u chi
rt gii.
Thut ton
Mi xem ta thy rng bt bin thua cho bi ny cng l N = M. D on ca bn gn ng v N = M
ch l mt trng hp c bit ca bt bin thua. D thy, nu N = M =1 th ht cch i. Nu N = M > 1 v
A i trc th B ch vic cn bng li s si ca hai ng l chc thng. Vy N = M l mt iu kin thua
(cho ngi i trc).
lp bng tnh tr ca hm f(N,M) ta cng nhn xt rng hm ny i xng, tc l f(N,M) =
f(M,N) v trt t ca cc ng si l khng quan trng. Cng chnh v f(N,M) l hm i xng nn ta ch
cn tnh tr ca f(N,M) vi N M ri ly i xng qua ng cho chnh ca bng tr. Vi mi N cho trc
ta ln lt in tng dng N ca bng vi M = N, N+1, N+2, Theo nhn xt trn ta c ngay f(N,N) = 0
vi mi N. T th thua ny ta thy ngay f(N,N+d) = 1 vi mi d = 1,2,N v t cc th ny ta c th bc d
vin t ng th hai (ng c M=N+d vin) dn n th thua f(N,N). T y suy ra th thua tip theo s
l f(N,N+N+1) = f(N,2N+1). Tng t, th thua tip sau th ny phi l f(N,2(2N+1)+1) = f(N,2 2N+2+1).
Tng qat ha ta thu c kt qu sau:
Nu ng si th nht c N vin th cc th thua s c dng f(N,M) vi M = 2 kN+2k1++2+1 =
k
2 N+(2k1++2+1). p dng cng thc
2k1 = (21)(2k1+2k2++2+1) = 2k1+2k2++2+1
k
k
ta thu c M = 2 N+2 1 hay M+1 = 2k(N+1).
Vy

100

Bt bin thua cho Bi Bc si F


S si trong hai ng tha h thc
(N+1) = 2k(M+1), k 0 (*)
T h thc (*) ta suy ra N = M l trng hp ring khi k = 0.
Hm Ket v th tc CachDi khi s nh sau.
rng cc s nguyn trong my tnh c biu din di dng nh phn nn gi tr 2 k tng ng vi
ton t dch tri 1 k bit, 1 shl k.
function Ket(N,M : integer) : integer;
var N1,M1,t: integer;
begin
N1 := N+1; M1 := M+1;
if N1 < M1 then
begin
t := N1; N1 := M1; M1 := t;
end; { N1 M1 }
while M1 < N1 do M1 := M1 shl 1; { 2*M1 }
if (M1 = N1) then Ket := 0 else Ket := 1;
end;
Vi th tc CachDi cho tnh hung thua th A nh bc 1 vin ng nhiu si. Trong trng hp
thng ta cng chn ng nhiu si bc bt S vin sao cho s si gia hai ng tha h thc (*). Ta tnh
S nh sau. Gi s N > M v k l s nguyn u tin tha h thc N+1 < 2 k(M+1). Khi , do iu kin
thng nn ta phi c 2k1(M+1) < N+1 < 2k(M+1) . Vy s si chnh lch cn bc bt ng nhiu si s l
S = N+12k1(M+1). Ta chng minh rng 1 S N/2. Tht vy, v 2k1(M+1) < N+1 nn S =
N+12k1(M+1) 1. Mt khc, nu S > N/2 th 2S > N hay 2N+2 2k(M+1) > N. T y rt ra N+1 >
2k(M+1)1, hay N+1 2k(M+1), mu thun vi gi thit v k.
procedure CachDi(N,M : integer; var D,S : integer);
var N1,M1,t: integer;
begin
{ N = M = 1: dau hang }
if (N = M) and (N = 1) then
begin
D := 0; S := 0;
exit;
end;
{ Chon dong nhieu soi }
if N > M then D := 1 else D := 2;
N1 := N+1; M1 := M+1;
if N1 < M1 then
begin
t := N1; N1 := M1; M1 := t;
end; { N1 M1 }
while M1 < N1 do M1 := M1 shl 1; { 2*M1 }
if (M1 = N1) then { Thua }
begin { Se Thua }
S := 1; { boc 1 vien }
exit;
end;
{ Cac tinh huong thang }
M1 := M1 shr 1;
S := N1-M1;
end;

101

// C#
static int Ket(int n, int m) {
if (n < m) {
int t = n; n = m; m = t;
} // n >= m
int n1 = n + 1, m1 = m + 1;
while (m1 < n1) m1 <<= 1;
return (m1 == n1) ? 0 : 1;
}
static void CachDi(int n, int m, out int d, out int s){
// n = m = 1: dau hang
if (n == m && n == 1){
s = d = 0;
return;
}
// Chon dong nhieu soi
d = (n >= m) ? 1 : 2;
int n1 = n + 1, m1 = m + 1;
if (n1 < m1) {
int t = n1; n1 = m1; m1 = t;
}// n1 >= m1
while (m1 < n1) m1 <<= 1;
if (m1 == n1) // thua {
s = 1; // boc 1 vien tai dong d
return;
}
// Cac tinh huong thang
m1 >>= 1; s = n1 - m1;
}

Bi 3.8. Chia Hnh ch nht


Olimpic Quc t
Cho mt li ch nht kch thc NM n v nguyn. Hai bn ln lt thc hin thao tc sau y:
Ct hnh theo mt ng k trong li i qua mt im nguyn trn mt cnh v khng trng vi nh
thu c 2 hnh ch nht sau vt i hnh c din tch nh hn, trao hnh c din tch ln hn cho ngi
kia. Nu hai hnh c din tch bng nhau th vt i mt hnh ty . Bn no n lt mnh khng th thc
hin c thao tc trn th thua. Hy cho bit bn i trc thng hay thua. Gi thit rng hai bn u chi
rt gii.

4.B
3.A
1.A

5.A

6.
B

2.B
Vi hnh ch nht 5 5 u th A s thua sau 6 nc i.
Sau mi ln ct, mnh trng c din tch ln hn
s c giao cho u th tip theo,
mnh xm s c b i.

102

Gi . Bi ny hon ton tng ng nh Bi Bc si F.

Bi 3.9. Bc si G
(Dng tng qut).
Cho N ng si vi s vin si ln lt l S i, i = 1,2,,N. Hai ngi chi A v B, A lun i trc. Lt
chi: Chn ng ty , bc ti thiu 1 vin v ti a na s vin ca ng. u th no n lt mnh m
khng i ni th thua. Hy cho bit A thng hay thua. Gi thit rng hai u th u chi rt gii.

Bi 3.10. Chia Hnh hp


(Cho trng hp 3 ng si)
Cho mt li hnh hp ch nht kch thc NMH n v nguyn. Hai bn ln lt thc hin thao
tc sau y: Ct hnh theo mt thit din i qua mt im nguyn trn mt cnh, khng trng vi nh v
vung gc vi cnh thu c 2 hnh hp ch nht sau vt i hnh c th tch nh hn, trao hnh c
th tch ln hn cho ngi kia. Nu hai hnh c cng th tch th vt i mt hnh ty . Bn no n lt
mnh khng th thc hin c thao tc trn th thua. Hy cho bit bn i trc thng hay thua. Gi thit
rng hai bn u chi rt gii.
gii bi 3 ng si chng ta cn mt cht tr gip ca ton hc. Bn xem ba mnh di y
v gii th mt s th d nh, sau th bt tay chng minh cc mnh . Bn cng c th xem li cc
chng minh trnh by trong cc bi gii ni trn.
C s ton hc
nh ngha 1. Cc s t nhin dng 2 k-1, k = 0, 1, 2, c gi l s Mersenne.
Th d, cc s 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023 l nhng s Mersenne ng vi cc gi tr k = 0, 1,
2, 3, 4, 5, 6, 7, 8, 9 v 10.
Cc s nm gia cc s trn th d, 2, 4, 5, 6, 8, 9, 10, 11, khng phi l s Mersenne.
Mnh 1. Cho s t nhin n. Nu n khng phi l s Mersenne th ta lun lun tm c s t nhin S, 1
S n/2 n-S l mt s Mersenne.
Th d,
1. n = 2, S = ?
2. n = 10, S = ?
3. n = 1534, S = ?
Gi . Xc nh k 2k < n+1 < 2k+1. Sau tnh S = n+1-2k.
p n: 1. S = 1; 2. S = 3; 3. S = 511.
Cho 2 s t nhin n v m. Xt h thc
n + 1 = 2k (m + 1), k = 0, 1, 2,
(*)
Mnh 2
a) Hai s Mersenne bt k u tha h thc (*).
b) C nhng cp s t nhin tha h thc (*) nhng khng phi l s Mersenne.
c) Nu cp s t nhin n v m tha h thc (*) v mt trong hai s l s Mersenne th s kia cng
phi l s Mersenne.
Gi
a) n= 2a-1, m = 2b-1,a b n+1 = (m+1).2a-b.
b) Th d, 5 v 11: (11+1) = (5+1).2 1, Vi mi a, b nguyn: 5 2a-1, 11 2b-1.
c) n+1 = (m+1).2k, n = 2a-1 2a = (m+1).2k hay m = 2a-k 1.
Mnh 3. Cho 2 s t nhin n v m, n > m. Nu n v m khng tha h thc (*) th ta lun lun tm c
s S, 1 S n/2 nS v m tha h thc (*).
Th d,
1. n = 12, m = 3 , S = ?

103

2. n = 50, m = 5, S = ?
3. n = 54, m = 6, S = ?
p n: 1. S = 5; 2. S = 3; 3. S = 27.
Gi . Xc nh k max 2k(m+1)< n+1. Sau tnh S = n+12k(m+1).
Tip theo s l bi ton bc nhiu ng si vi lut bc s qun khng hn ch trong mt ng duy
nht chn.

Bi 3.11. Tr chi NIM


Tr chi NIM c xut x t Trung Hoa, dnh cho hai u th A v B vi cc nc i ln lt an nhau
trn mt u trng vi N ng si. Ngi no n lt i th c chn ty mt ng si v bc ti
thiu l 1 vin, ti a l c ng chn. Ai n lt mnh khng th thc hin c nc i s thua. Ta
gi thit l A lun i trc v hai u th u chi rt gii. Cho bit A thng hay thua?
Thut ton
Gi s vin si trong cc ng l S1, S2,, SN.
K hiu l tng loi tr (xor). t x = S1 S2 SN. Ta chng minh rng bt bin thua ca
tr chi NIM l x = 0, tc l nu x = 0 th n lt ai i ngi s thua.
Trc ht nhc li mt s tnh cht ca php ton theo bit.
1) a b = 1 khi v ch khi a b.
2) a 0 = a
3) a 1 = not a
4) Tnh giao hon: a b = b a
5) Tnh kt hp: (a b) c = a (b c)
6) Tnh ly linh: a a = 0
7) a b a = b
8) Tnh cht 7 c th m rng nh sau: Trong mt biu thc ch cha php xor ta c th xa i chn
ln cc phn t ging nhau, kt qu s khng thay i.
d nh ta gi php ton ny l so khc so xem hai i tng c khc nhau hay khng. Nu
khc nhau l ng (1) ngc li l sai (0).
Bt bin x = 0 c ngha nh sau: Nu vit cc gi tr Si, i = 1..N di dng nh phn vo mt bng
th s lng s 1 trong mi ct u l s chn.
Dng nh phn
S1 = 13 1

S2 = 14 1

S3 = 6

S4 = 7

S5 = 2

x = 0 0

Bng bn cho ta S1S2S3S4S5 = 1314672 = 0.


Nu x l tng xor ca cc Si, i = 1..N, vi mi i = 1..N ta k hiu
K(i) l tng xor khuyt i ca cc Si vi cch tnh nh sau: K(i) = S1 S2
Si-1 Si+1 SN. Nh vy K(i) l tng xor ca cc Sj sau khi
loi tr phn t Si v x chnh l tng xor ca cc Si, i = 1..N. Do Si
Si = 0 v 0 y = y vi mi y nn K(i) = x Si. cho tin, ta cng
k hiu K(0) chnh l tng xor ca cc Si, i = 1..N. Vi th d cho
ta tnh c cc tng khuyt nh sau:
K(0) = S1S2S3S4S5 = 1314672 = 0.
K(1) = S2S3S4S5 = 14672 = 13,

K(2) = S1S3S4S5 = 13672 = 14,


K(3) = S1S2S4S5 = 131472 = 6,
K(4) = S1S2S3S5 = 131462 = 7,
K(5) = S1S2S3S4 = 131467 = 2.
Ta pht hin c qui lut l th sau y:

104

Mnh 1. Cho x l tng xor ca N s t nhin, Si, x = S1S2...SN. Khi K(i) = x Si, i =
1,2,...,N. Tc l mun b mt s hng trong tng ta ch vic thm tng vi chnh s hng . Ni
ring, khi x = 0 ta c K(i) = Si, i = 1,2,...,N.
Chng minh
Gi x l tng xor ca cc s cho, x = S1S2...SN. Vn dng nh giao hon v tnh ly ng
ta c th vit x Si = (S1S2...Si-1Si+1SN)(SiSi) = K(i) 0 = K(i), i = 1,2,...,N, pcm.
Ta chng minh tip cc mnh sau:
Mnh 2. Nu x 0 th c cch i hp l bin i x = 0.
Chng minh
Do x 0 nn ta xt ch s 1 tri nht trong dng biu din nh phn ca x = (xm, xm-1,,x0), xj = 1, xi
= 0, i > j. Do x l tng xor ca cc Si, i = 1..N, nn tn ti mt Si = (am, am-1,,a0) ch s aj = 1. Ta chn
ng Si ny (dng c du *). Khi , ta tnh c K(i) = x Si = (xmam, xm-1am-1,,x0a0) = (bm, bm1,,b0) vi bi = xiai, 0 i m. Ta c nhn xt sau y:
* Ti cc ct i > j: bi = ai, v bi = xiai = 0 ai = ai,
* Ti ct j ta c: bj = 0, v bj = xj aj = 1 1 = 0.
Do aj = 1, bj = 0 v mi v tr i > j u c bi = ai nn Si > K(i). Nu ta thay dng Si bng dng K(i)
th tng xor y khi s l
y = (x Si) K(i) = K(i) K(i) = 0.

Dng nh phn

Vy, nu ta bc ti ng i s vin si v = SiK(i) th s si cn li


x3 x2 x1 x0
trong ng ny s l K(i) v khi tng xor s bng 0, pcm.
1 0
0
Mnh 3. Nu x = 0 v cn ng si khc 0 th mi cch i hp l S1 = 12 1
u dn n x 0.
S2 = 14 1
1 1
0
Chng minh
* S3 = 6 0
1 1
0
Cch i hp l l cch i lm gim thc s s si ca mt ng
0
0 1
1
Si duy nht no , 1 i N. Gi s ng c chn l Si = (am, am- S4 = 3
,,a
).
Do
S
b
sa
nn
chc
chn
c
mt
bit
no

b
o
(t
0
1
0
i
S5 = 2
0
0 1
0
thnh 1 hoc t 1 thnh 0). Ta gi bt b sa l aj. Khi tng s bt
1 trn ct j s b tng hoc gim 1 n v v do s khng cn l s x = 5 0
1 0
1
chn. T suy ra rng bit j trong x s l 1, tc l x 0 pcm.
Phn lp lun ch yu trong mnh 2 nhm mc ch ch ra s tn ti ca mt tp Si tha tnh cht
Si > xSi. Nu tm c tp Si nh vy ta s bc Si(xSi) vin ti ng si i.
Gi thit rng mng S[1..N] kiu nguyn cha s lng si ca mi ng khi to nh mt i tng
dng chung, ta vit hm Ket v th tc CachDi nh sau.
Hm Ket s cho ra gi tr l tng xor x ca cc ng si. Nh vy, khi x = 0 th ngi no i s thua,
ngc li, khi x 0 th ngi no i s thng.
function Ket(N: integer): integer;
var x, i: integer;
begin
x := 0;
for i := 1 to N do x := x xor S[i];
Ket := x;
end;
Th tc CachDi hot ng nh sau:
Gi hm x = Ket. Nu x = 0 tc l s thua th chn mt ng cn si, th d ng cn nhiu si nht,
bc tm 1 vin nhm ko di cuc chi. Nu x = 0 v cc ng u ht si th ng nhin l phi chu
thua. Trng hp x 0 th ta tm cch i chc thng nh sau:
Bc 1. Tm ng si i tha iu kin x Si < Si.
Bc 2. Bc ti ng i Si (xSi) vin.

105

procedure CachDi(N: integer; var D,V: integer);


var x,i: integer;
begin
x := Ket(N);
if x = 0 then { Thua }
begin
D := 1;
for i := 2 to N do
if (S[i] > S[D]) then D := i;
if (S[D] = 0) {Het soi: Dau hang}
then D := 0
else S := 1;
exit;
end;
{ Chac thang }
for D:=1 to N do
if (s[D] > (x xor S[D])) then
begin
V := S[D]-(x xor S[D]); {boc V vien tai dong D }
exit;
end;
end;
Trong cc hm C# di y mng s c khai bo n phn t, cc phn t c m s t 0 n n 1, trong
khi cc ng si c m s t 1 n n do chng ta phi lu chuyn i ch s cho thch hp

// C#
static int Ket() {
int x = 0;
for (int i = 0; i < s.Length; ++i) x ^= s[i];
return x;
}
static int CachDi(ref int d, ref int v) {
int x = Ket();
if (x == 0) { // Thua
d = 0;
for (int i = 1; i < s.Length; ++i)
if (s[i] > s[d]) d = i;
// s[d] = Max(s[i] | i = 0..n-1)
if (s[d] > 0){ v = 1; ++d; }
return x;
}
// Thang
for (d = 0; d < s.Length; ++d)
if ((x ^ s[d]) < s[d]){
v = s[d] - (x ^ s[d]);
++d;
return x;
}
return x;
}

Bi 3.12. C bng
Bn c l mt tm bng ch nht N dng m s t trn xung ln lt l 1, 2,...,N v M ct m s t
tri sang ln lt l 1,2,...,M; 2 N 500, 2 M 50. Mt qun c @ c t ti dng x, ct y. Hai u
th A v B lun phin mi ngi i mt nc nh sau: buc phi chuyn qun c @ t ct hin ng l y

106

sang ct k ty chn nhng phi khc ct y. Vic chuyn ny phi c thc hin nghim ngt nh sau:
trc ht y ngc qun c @ ln k dng. Nu qun c vn cn trong bng th r phi hoc tri t
qun c vo ct k, ngc li nu qun c ri ra ngoi bng th coi nh thua.
Nh vy, nu qun c ang t ti v tr (x,y) mun chuyn qun c sang ct k y th trc ht phi
y qun c n dng x-k. Nu x-k 1 th c php t qun c vo v tr mi l (x-k,k).
Gi thit A lun lun l u th i nc u tin v hai u th u chi rt gii. Bit cc gi tr N,
M, x v y. Hy cho bit A thng (ghi 1) hay thua (ghi 0)?
s

A3

B2

A1

Vi N = 8, M = 4, qun c @ t ti v tr xut pht (7,2) v A i trc ta


thy A s thng sau 3 nc i an xen tnh cho c hai u th nh sau:
1. A chuyn @ t v tr @(7,2) sang v tr A1(4,3)
2. B chuyn @ t v tr A1(4,3) sang v tr B2(3,1)
3. A chuyn @ t v tr B2(3,1) sang v tr A3(1,2)
B chu thua v ht cch i!
Thut ton
Ta th vn dng k thut Nhn - Qu in tr 1/0 vo mi (i, j)
ca bng a vi ngha nh sau: nu gp th c c qun c @ t ti v tr (i, j) th
ai i trc s thng (1) hay thua (0). Ta s duyt theo tng dng t 1 n N, trn
mi dng ta duyt t ct 1 n ct M.
Ta c nhn xt quan trng sau y. Nu (i, j) = 0 tc l gp th thua th
cc i n c ny s l nhng th thng. chnh l cc (i+j, k) vi 1 k
M v k j.

T nhn xt ny ta vit ngay c hm Ket - kim tra Nhn xt


xem ngi i trc vi qun c @ ti (x,y) trn bn c NM Nu [i, j] = 0 th mi trn dng i+j,
s thng (1) hay thua (0).
tr (i+j, j) u nhn tr 1.
Trc ht ta lp y tr 0 cho bng - mng hai chiu
a[1..N, 1..M] kiu byte, sau ln lt duyt cc phn t ca [i, j] = 0 [i+j, k] = 1, k = 1..M, k j.
bng v in tr 1 theo nhn xt trn.
function Ket(x,y: integer): integer;
var i,j,k: integer;
begin
fillchar(a,sizeof(a),0);
for i := 1 to x-1 do
for j := 1 to Min(x-i,M) do
if (a[i,j] = 0) then
{ in 0 cho cc (i+j, k); k=1..M, k j }
for k := 1 to M do
if (k <> j) then a[i+j,k] := 1;
Ket := a[x,y];
end;
Thut ton trn i hi phc tp c N.M2.

107

Lp y 0 (bng tri) ri in tr (bng phi)


cho c bng N = 8, M = 4.
Kt qu vi x = 7, y = 2: a[7,2] = 1 (A thng).
tham gia cuc chi vi cc gi tr N, M v (x,y) cho trc d nhin bn cn tnh trc bng a
theo th tc Ket ni trn. Sau , mi ln cn i bn chn nc i theo hm CachDi nh m t di y.
Hm nhn vo cc gi tr N, M l kch thc dng v ct ca bng; dng sx, ct sy l v tr ang xt ca
qun c @ v cho ra mt trong ba gi tr loi tr nhau nh sau:
CachDi = 1 nu tm c mt v tr chc thng (nx,ny) t qun c;
CachDi = 0 nu khng th tm c v tr chc thng no nhng cn nc i do buc phi i
n v tr (nx,ny);
CachDi = -1 nu ht cch i, tc l chp nhn thua kt thc vn c.
Ta thy sau khi gi th tc Ket th dng u tin ca bng a cha tan 0 v phn t a[2,1] cng
nhn tr 0. l nhng th buc phi u hng v ht cch i. Vy tnh hung u hng (hay ht cch i)
s l
sx = 1, hoc
sx = 2 v sy = 1.
Ngoi ra, do th tc Ket c gi, tc l bng a c in th hin mi cch i ca cuc chi
nn a[sx,sy] cho ta ngay gi tr chc thng hoc chc thua ca tnh hung xut pht t (sx,sy).
Nu a[sx,sy] = 0 ta nh chn nc i c th thua chm theo Heuristic sau y: Tm cch y qun
c @ t v tr (sx,sy) ln cng t cng tt.
Nu a[sx,sy] = 1 ta chn nc i c th thng nhanh theo Heuristic sau y: Tm cch y qun c
@ t v tr (sx,sy) ln cao nht c th c, tc l ln v tr (nx, ny) tha ng thi cc iu kin
a[nx, ny] = 0,
nx cng nh cng tt.
Sau ny ta s thy cc Heuristics trn ch l mt cch i tt ch cha phi l cch i ti u.
function CachDi(M, sx, sy: integer; var nx,ny: integer): integer;
begin
if (sx = 1) or ((sx = 2) and sy = 1)) then
begin { Het cach di: Dau hang }
CachDi := -1;
exit;
end;
CachDi := a[sx,sy];
if CachDi = 0 then { Con nuoc di nhung se thua }
for ny := 1 to Min(sx-1,M) do
if (ny <> sy) then
begin
nx := sx ny;
exit;
end;
{ Chac thang }
for ny := Min(sx-1,M) downto 1 do
if (ny <> sy) then
if (a[sx-ny,ny] = 0) then
begin { chac thang }
nx := sx ny; exit;
end;
end;

108

end;
Hm Min(a,b) cho ra gi tr min gia hai s a v b cn dc m t trc nh sau:
function Min(a,b: integer): integer;
begin
if (a < b) then Min := a else Min := b;
end;
Chng trnh C# di y m t mt vn C Bng 50 7 gia hai u th A (i trc) v B. Qun
c xut pht ti v tr (49,5). Vn ny A s thng.
using System;
using System.Collections.Generic;
using System.Text;
namespace ConsoleApplication1 {
class Program {
static int maxn = 501, maxm = 51;
static int[,] a = new int [maxn,maxm];
static void Main(string[] args){
Game(50, 7, 49, 5);
Console.WriteLine("\n \n Fini");
Console.ReadLine();
}
static void Game(int n, int m, int x, int y) {
Console.WriteLine("\n The co " + n +
" X "+m+" @ = ("+x+","+y+")");
Ket(m, x, y);
Show(a, x, m);
while (true) {
Console.Write("\n A: ( " + x + " , " + y + " ) ");
if (CachDi(m, x, y, ref x, ref y) == -1) {
Console.Write("Dau hang !!!");
Console.ReadLine();
return;
}
else Console.Write(" ==> ( " + x + " , " + y + " ) ");
if (Console.Read() == '.') return;
Console.Write("\n B: ( " + x + " , " + y + " ) ");
if (CachDi(m, x, y, ref x, ref y) == -1) {
Console.Write("Dau hang !!!");
Console.ReadLine();
return;
}
else Console.Write(" ==> ( " + x + " , " + y + " ) ");
if (Console.Read() == '.') return;
} // while
}
static int CachDi(int m, int sx, int sy, ref int nx, ref int ny)
{
if (sx == 1 || (sx == 2 && sy == 1)) return -1;
if (a[sx, sy] == 0) { // Di duoc, nhung thua
for (ny = 1; ny <= Min(sx-1,m);++ny)
if (ny != sy) { nx = sx - ny; return 0; }
}
for (ny = Min(sx-1,m); ny > 0; --ny)
if (ny != sy)
if (a[sx - ny, ny] == 0) // Chac thang
{ nx = sx - ny; return 1; }

109

return 0;
}
static int Min(int a, int b) { return (a < b) ? a : b; }
static int Ket(int m, int x, int y) {
Array.Clear(a,0,a.Length);
for (int i = 1; i < x; ++i) { // voi moi dong i
int minj = Min(x - i, m);
for (int j = 1; j <= minj; ++j) // xet cot j
if (a[i, j] == 0)
for (int k = 1; k <= m; ++k)
if (k != j) a[i + j, k] = 1;
}
return a[x, y];
}
static void Show(int[,] s, int n, int m) {
Console.WriteLine();
for (int i = 1; i <= n; ++i) {
Console.Write("\n"+i+". ");
for (int j = 1; j <= m; ++j)
Console.Write(a[i, j] + " ");
}
}
}// Program
}
Nu N c kch thc ln, th d, c triu dng, cn s ct M vn nh, th d M 50 v ra ch
yu cu cho bit ngi i trc thng hay thua ch khng cn l gii tng nc i th ta vn c th s dng
mt mng nh c 5151 phn t gii bi ton trn. Ta khai bo kiu mng nh sau:
const mn = 51;
type
MB1 = array[0..mn] of byte;
MB2 = array[0..mn] of MB1;
var a: MB2;
N: longint;
M: integer;
....
Ta s dng mng index di y chuyn i cc s hiu dng tuyt i thnh s hiu ring trong
mng nh a. bn ch cn lu nguyn tc sau y khi x l cc php thu gn khng gian: Khng ghi vo
vng cn phi c d liu. Thc cht y l mt hm bm cc gi tr i trong khong 1..N vo min 0..M
bng php chia d: i (i-1) mod (M+1) nh m t trog hm index.
function index(i,M: integer): integer;
begin
index := i mod (M+1);
end;
function Ket(M: integer;
x: longint; y: integer): integer;
var i: longint; j,k: integer;
begin
fillchar(a,sizeof(a),0);
for i:= 1 to x-1 do
begin
k := index(i+M,M);
fillchar(a[k],sizeof(a[k]),0);
for j:=1 to Min(x - i, M)do
if (a[index(i,M),j] = 0) then
for k := 1 to M do

110

if (k <> j) then
a[index(i+j,M),k] := 1;
end;
Ket := a[index(x,M),y];
end;

//C#
static int Index(int i, int m) { return i % (m + 1); }
static int Ket(int m, int x, int y){
int id, Minj, i, j, k, v ;
Array.Clear(a, 0, b.Length);
for (i = 1; i < x; ++i) {
id = Index(i + m, m);
for (v = 1; v <= m; ++v) a[id, v] = 0;
minj = Min(x - i, m);
for (j = 1; j <= minj; ++j) // xet cot j
if (a[Index(i, m), j] == 0)
for (k = 1; k <= m; ++k)
if (k != j) a[Index(i + j, m), k] = 1;
}
return a[Index(x,m), y];
}
n y ta th m rng iu kin ca bi ton nh sau: Hy cho bit, vi cc gi tr cho trc l
kch thc bng N M, v tr xut pht ca qun c @ (x,y) v u th A i trc th A thng hoc thua sau
bao nhiu nc i ?
Nguyn tc ca cc tr chi i khng
Nu bit l thng th tm cch thng nhanh nht,
Nu bit l s thua th c ko di cuc chi
c th thua chm nht.
Ta vn s dng bng A in tr vi cc qui c mi sau y:
Nu t (i, j) ngi i trc c th thng sau b nc i th ta t a[i,j] = +b; ngc li nu t ny
ch c th dn n th thua sau ti a b nc i th ta t a[i,j] = b. Mt nc i l mt ln di chuyn qun
c ca mt trong 2 ngi chi. Ta cng qui c a[i,j] = 0 c ngha l u th xut pht t (i,j) s ht cch
i do chp nhn thua ngay. K hiu (i,j) (u,v) nu c nc i hp l t (i,j) sang (u,v). T nguyn
tc ca cc tr chi i khng ta suy ra
(1) Nu t (i,j) c nhng nc i hp l dn n th (lm cho i phng) thua th ta chn
cch thng nhanh nht bng cch t
a[i,j] = min { a[u,v] | (i,j) (u,v), a[u,v] 0 } + 1
(2) Nu t (i,j) mi nc i hp l u dn n th (to cho i phng thng) th ta phi
chn cch thua chm nht bng cch t
a[i,j] = (max { a[u,v] | (i,j) (u,v), a[u,v] > 0 } + 1)

111

Sau khi lp y 0 cho bng a ta ln lt duyt cc dng i t 1 n x. Vi mi


dng ta duyt cc ct j t 1 n M. Nu gp tr a[i,j] = 0 ta hiu l v tr ny s dn
n thua. Ta cn tnh s bc thua chm nht ri gn cho a[i,j]. Tip n, do v tr
(i,j) l thua nn ta phi cp nht li cc gi tr a[u,v] ng vi cc v tr (u,v) (i,j).
Bn th in tr cho bng a vi N = 12, M = 4. Trong th d ny, a[8,2] = - 4
c ngha l nu qun c @ t v tr (8,2) th ngi i trc s thua sau 4 nc
i. Tht vy, gi A l ngi i trc, ta thy nu A di chuyn @ n (7,1) th B s
i tip thng sau 3 nc i; A khng th n dng 6 (?). Nu A n (5,3) th B
s i tip thng sau 1 nc. Nu A n (4,4) thi B s i tip 1 nc na n
(1,3) l thng.
Ti sao trong hm Ket ta phi tnh th thua trc khi tnh th thng. V khi
gp a[i,j] = 0 th ta cn cp nht gi tr ny bit c l s thua sau bao nhiu
nc i. Sau , do c ch lp lun li, ch khi no ta bit s nc thua ti a[i,j] th
mi tnh tip c cc th thng dn n h thua ny.
function Ket(M,x,y: integer): integer;
var i, j: integer;
begin
fillchar(a,sizeof(a), 0);
for i := 1 to x do
for j := 1 to M do
if (a[i,j] = 0) then
begin
TinhNuocThua(M,i,j);
TinhNuocThang(M,x,i,j);
end;
Ket := a[x,y];
end;
Procedure TinhNuocThua(M,i,j: integer);
var k, vmax: integer;
begin
vmax := -1;
for k := 1 to Min(i-1,M) do
if (k <> j) then
vmax := Max(vmax, a[i-k,k]);
a[i,j] := -(vmax + 1);
end;
Procedure TinhNuocThang(M,x,i,j: integer);
var k, d, v: integer;
begin { Xet dong i+j }
d := i+j;
if (d <= x) then { quan co con trong vung can xu ly }
begin
v := -a[i,j] + 1;
for k := 1 to M do
if (k <> j) then
if (a[d,k] > 0) then a[d,k] := Min(a[d,k], v)
else a[d,k] := v;
end;
end;

-2 1

-2 -2 -2 -2

-4 3

10 3

-2

11 -4 -4 -4 -4
12 -4 5

Tab Game vi
N = 12, M = 4.

// C#
static int Ket(int n, int m, int x, int y) {
Array.Clear(a, 0, a.Length);
for (int i = 1; i <= x; ++i) { // voi moi dong i
for (int j = 1; j <= m; ++j) // xet cot j

112

if (a[i, j] == 0) {
TinhNuocThua(m, i, j);
TinhNuocThang(m, x, i, j);
}
}
return a[x,y];
}
static void TinhNuocThua(int m, int i, int j) {
int vmax = -1, km = Min(i-1,m);
for (int k = 1; k <= km; ++k)
if (j != k) vmax = Max(vmax, a[i - k, k]);
a[i,j] = -(vmax + 1);
}
static void TinhNuocThang(int m, int x, int i, int j){
int d = i + j;
if (d > x) return;
int vmin = -a[i,j]+1;
for (int k = 1; k <= m; ++k)
if (k != j)
a[d,k] = (a[d, k] > 0) ? Min(a[d, k], vmin) : vmin;
}
Vi N c triu v M nh bn cng c th vn dng cc k thut tng t nh trnh by c
th tnh s nc thng/thua, tuy nhin trong trng hp ny bn phi khai bo mng a rng gp i, tc l a
phi cha 2M+2 dng gm M dng trc dng ang xt v M dng sau dng ang xt. cc dng trc v
sau ny dng cp nht s nc i thng/thua.
0 1
2
3
4
n y ta c th s dng thut ton C bng gii bi C y
1
0
0
0
0
sau y.
2

Bi 3.13. C y

Bn c l mt gii bng chia m s t 1 n N. Hai u th A v


B
an
xen
nhau, mi ngi i mt nc, A lun i trc. Mt qun c @
4
1
1 -2 1
t cnh x. Ti nc i th i phi y qun c ln (v pha ch s nh) d i
5
1
1
1 -2 , 1 d M v khng c lp li cch va i ca u th trc, tc l
i
d

d
.
i
i-1 u th no n lt mnh khng i ni th thua. Gi thit l hai
6
-2 -2 -2 -2
u th u chi rt gii. Bit N, M, x v A l u th i trc. Hy cho
7
@ 3
3
3
3
bit
a) A thng (ghi 1) hay thua (ghi 0).
8
3 -4 3
3
b) A thng hay thua sau bao nhiu ni i?
9
3
3
3
3
Gi s hai u th i v nc i vi mc y ln lt l d 1, d2 ,..., dv
10
3
3
3
5
th gi thit ca bi cho bit hai mc y k nhau l di-1 v di phi khc
11
-4 -4 -4 -4 nhau. Gi s bn c c N = 12 , qun c t cnh x = 7, mi nc i
phi di chuyn qun c ln 1, 2.., hoc M = 4 v khng c lp li nc
12
-4 5
5
5
va i ca ngi trc. Nu A i trc th s c th thng sau ti a 4 nc
i. Chng hn, A i ln 1 bc d1 = 1 n 6. B c th chn mt trong 3
C y N = 12, M = 4, x = 7
cch i ng vi d2 = 2, 3, hoc 4. n 4, 3 hoc 2. Nu B chn d 2 =
v Tab Game tng ng.
2 n 4 th A di chuyn ln theo d3 = 3 n 1 khin cho B thua.
Nu B chn d2 = 3 n 3 th A di chuyn ln theo d 3 = 2 n 1
khin cho B thua. Cui cng, nu B chn d = 4 n 2 th A di chuyn ln theo d 3 = 1 n 1 khin
cho B thua. cc gi tr di theo tng phng n khi l nh sau:
Phng n 1: (1, 2, 3).
Phng n 2: (1, 3, 2).
Phng n 3: (1, 4, 1).
Thut ton

113

Chng ta hy thit lp s tng ng gia c y v c bng v ch ra rng A thng c y khi v ch


khi A thng c bng tng ng. C y N , gii hn bc i M v xut pht x tng ng vi c bng N
di, M ngang v v tr xut pht (x,y) trong y = d 1 l nc i hp l u tin n 1 thua, x := x-d1.
C mt cch t duy c th d dng tnh c (x,y) nh sau. Ta thm cho c bng mt gi mang
m s 0 v qui nh rng qun c bng xut pht ti (x,0) - dng v, ct 0. Sau , trong cuc chi vi c
bng ny khng ai c php di chuyn n ct 0. Nu A i u tin th chc chn s di chuyn t (x,0)
n mt m B chc thua. Trong th d ny, nc i u tin ca A s l (7,0) (6,1), tc l chuyn qun
c t ct 0 sang ct 1.
Bi c y mi xem tng nh n gin nhng gii c ta li phi xt bi kh hn nhng c li
gai trong sng, d hiu

Bi 3.14. Bc si H
Dng pht biu khc ca bi C y
Cho ng si N vin, hai u th A v B ln lt i, A i nc u tin. Mi nc i u th buc
phi bc ti thiu 1 vin, ti a M vin trong ng v khng c lp li nc va i ca ngi trc. Th
d, nu u th A va bc v vin si th n lt mnh, u th B khng c bc v vin na. u th no
n lt mnh khng i ni th thua. C hai u th u chi rt gii. Cho bit a) A thng hay thua. b) A
thng hay thua sau bao nhiu ni i?

114

C h ng 4
C c th ut t o n s p t

4.1 C tam ti
Olimpic quc t
Mt s quc gia nh Ba Lan, B, Php c
quc k to t ba gii mu thng c gi l c
tam ti. Ba bn tr A, B v C chi tr ghp hnh
to thnh mt l c tam ti vi ba gii mu dc ln
A
lt tnh t tri qua phi l xanh (X), trng (T) v
(D). Mt bn ghp c c kch thc 2N 3N
vung n v c k sn thnh li vung vi
C
m s cc hng tnh t trn xung di l 1, 2,,
2N v m s cc ct tnh t tri qua phi l 1, 2,,
3N. u tin bn A chn mt trn ct 1 c ta
B
l (Ax, Ay = 1), bn B chn mt trn dng cui
cng c ta l (Bx=2N, By), bn C chn mt
trn ct cui cng c ta l (Cx, Cy = 3N). Sau
C tam ti 4 6
ln lt theo th t quay vng A, B, C ba bn
N=2
chn cc mnh ghp n v 1 1 vi mu ph hp
t vo cc trong bn c. Ln u tin mi
bn t mt mnh ghp vo chn. Nhng ln tip theo, n lt mnh, mi bn t mt s mnh ghp
k vi mnh ghp do chnh bn y t ti ln trc. D nhin, mi trn bn ch c t ng 1 mnh
ghp. Bn no khng th ghp c th bn ngng chi, nhng ngi cn li s tip tc chi n khi
hon thnh l c. Bit cc gi tr N, Ax, By v Cx. Hy cho bit mi bn ghp c bao nhiu mnh mi
mu.
Vi th d nh trong hnh, N = 2, Ax = 2, By = 2, Cx = 3 ta tnh c kt qu nh trong bng.
ngha ca cc trn bn ghp c cho bit bn no trong ln i th my ca mnh, ghp mnh mu g. Th
d, A5:T cho bit bn A, trong ln i th 5 ghp mnh mu trng. xut pht ca mi bn k hiu l 0.

A1:X

A2:X

A3:T

A4:T

C3:D

C2:D

A0:X

A1:X

A2:T

A3:T

C2:D

C1:D

Xanh
A

Trng
4

115

A1:X

B1:X

B2:T

C2:T

C1:D

C0:D

B1:X

B0:X

B1:T

B2:T

C2:D

C1:D

C tam ti, N = 2, A(2,1), B(4,2), C(3,6)


X: Xanh, T: Trng, D: .

Kt qu

Thut ton
Bi ny kh d gii. Nu bn kho t chc d liu th chng trnh s rt gn. Trc ht ta cn xc
nh rng mi (i,j) trn bn c s do bn no ghp: A, B hay C ? Ta nh ngha khong cch gia hai
(i,j) v (x,y) trn bn c l s t nht nm trn ng i t ny n kia qua cc k cnh nhau.
Khong cch ny chnh l tng chiu di hai cnh k nhau ca hnh ch nht nhn hai cho lm hai
nh i din, do c tnh theo cng thc
d = abs(i-x) + abs(j-y) +1
Gi tr d c ngha g ? Nu ta qui nh nh s cc ln i cho mi u th l 0, 1, 2, th d-1 cho
bit ln i th my ca mi bn. V trt t tnh ln i ca cc bn l A B C nn ta cn xc nh gi tr
min trong ba khng cch d A, dB v dC. Tuy nhin chng ta s khn ngoan mt cht, c th l ta s tnh d
theo cng thc ht 1
d = abs(i-x) + abs(j-y)
v vit hm min3 nhn vo l ba gi tr d A, dB v dC v cho ra l tn ca ngi c ghp mnh ti
ang xt.
function Min3(a,b,c: integer): char;
var k: char;
begin
k := 'A';
if a > b then begin k := 'B'; a := b end;
if a > c then k := 'C';
Min3 := k;
end;
Sau khi xc nh c ch ca mnh ghp ti (i,j) ta d dng tnh c mu ca mnh ghp ti
. V l c c ba mu v ta tm qui c cc gii mu tnh t tri qua phi l 0, 1 v 2 nn mu cn chn
t ti (i,j) khi s l (j-1) div N.
Ta khai bo mng kq dng tch ly kt qu nh sau:
kq: array['A'..'C',0..2] of integer;
Khi c[v,i] s cho bit bn v ghp bao nhiu qun mu i, v = 'A', 'B', 'C'; i = 0 (mu Xanh), 1
(mu Trng), 2 (mu ).
Cc bin chung ca chng trnh s l:
var
n: integer; { Ban co co kich thuoc 2n3n }
Ax,Ay,Bx,By,Cx,Cy: integer; { Toa do xuat phat cua A, B, C }
kq: array['A'..'C',0..2] of integer; { Chua ket qua }
Th tc XuLi s duyt ln lt mi (i , j) trn bn c, xc nh ch nhn ca ny v s mu ca
mnh cn ghp tch ly cho ch nhn .
procedure XuLi;
var i,j: integer;
begin
fillchar(kq,sizeof(kq),0);
for I := 1 to 2*N do
for j := 1 to 3*N do
inc(c[Min3(abs(i-Ax)+abs(j-Ay),abs(i-Bx)+abs(j-By),

116

abs(i-Cx)+abs(j-Cy)),(j-1) div N]);


end;

Chng trnh C#
Chng trnh C# di y thc hin vi d liu cho trc N = 2, A(2,1), B(4,2), C(3,6).

// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao2 {
class CoTamTai {
static int n = 2; // Ban co kich thuoc 2N3N
static int [,] kq = new int [3,3];
static int Ax = 2, Ay = 1, Bx = 2*n, By = 2,
Cx = 3, Cy = 3*n; // Toa do xuat phat
static void Main(string[] args) {
XuLi();
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j)
Console.Write(KQ[i, j] + " ");
Console.WriteLine();
}
Console.ReadLine();
}
static int Min3(int a, int b, int c) {
int min = 0;
if (a > b) { min = 1; a = b; }
if (a > c) min = 2;
return min;
}
static void XuLi() {
Array.Clear(Kq,0,Kq.Length);
int n2 = 2 * n;
int n3 = 3 * n;
for (int i = 1; i <= n2; ++i)
for (int j = 1; j <= n3; ++j)
++KQ[Min3(Math.Abs(i-Ax)+Math.Abs(j-Ay),
Math.Abs(i-Bx)+Math.Abs(j-By),
Math.Abs(i-Cx)+Math.Abs(j-Cy)),(j-1)/n];
}
} // Co Tam Tai
} // SangTao2

phc tp
Ta phi duyt mi trn bn c vy phc tp tnh ton c N2.
Bi sau y tng t nh bi trn nhng kh hn v cc th tc m ha.

4.2 Li tam gic u


Cho tam gic u ABC, nh A, cnh di N n v. Ti cc im chia nguyn trn cc cnh ta k cc
ng thng song song chia tam gic thnh N2 tam gic n v (TGV). M s cho cc TGV theo trt t
t trn xung v t tri qua phi l 1, 2, , N 2. Ba bn A, B v C c cp mi bn mt TGV khc nhau
lm ni xut pht trn cc cnh AB cho bn A, BC cho bn B v AC cho bn C. Ln lt theo th t quay

117

1
3

10

A2

11

13
12

C9
15
B14

16

Li Tam gic N = 4, NA = 2, NB = 14,


NC = 9.
Kt qu, A: 9, B: 5, C: 2.

vng A, B, C vit ch ci tn mnh vo cc TGV k cnh vi cc tam gic m mnh vit ln


trc. Bit cc gi tr N, v cc im xut pht NA, NB v NC, tnh s ch ci mi loi mi bn vit.

T chc d liu
Cc bin dng chung:
var n: longint; { Do dai canh tam giac }
f,g: text; { input, output file }
AN, BN, CN: longint; { O xuat phat }
Ad, Av, Bd, Bv, Cd, Cv: longint; { Toa do xuat phat }
Ak,Bk,Ck: longint;
A,B,C: longint; { con dem }
Kq: array [A..C] of longint;
trong n l chiu di mt cnh ca tam gic u; AN, BN v CN l s hiu ca cc xut pht
tng ng cho A, B v C.

Thut ton
Xt cc tam gic n v t nh xung n cnh y ca bn c. Ta thy, trn dng 1 c 1 TGV,
dng 2 c 3, dng 3 c 5 TGV... Tng qut, trn dng i tnh t nh xung n y s c 2*i -1 TGV.
Trn mi dng i ta gn s hiu cho cc TGV l 1, 2, ... , 2i-1. Ta nh ngha ta ca mt tam gic
n v c s hiu (tuyt i theo u bi) cell l cp s (d,v) trong d l s hiu dng cha TGV v v
l s hiu ca tam gic trn dng d. Th tc ToaDo di y tnh ta cho mt TGV theo cell - s
hiu (tuyt i) ca TGV nh cch m s ca bi. Th tc cho ra hai gi tr, dong - dng cha TGV
cell v viTri - s hiu ca TGV trn dng m ta gi l s hiu tng i. Th d, ToaDo(15,d,v)
cho ta d = 4, v = 6.

118

procedure ToaDo(cell: longint;var dong, viTri:longint);


begin
dong := 0;
while cell > 0 do
begin
dong := dong + 1;
cell := cell - (2*dong-1);
end;
viTri := cell + (2*dong-1);
end;
Hm KhoangCach di y tnh khong cch gia hai TGV theo ta (d1,v1) v (d2,v2),
trong d1, d2 l s hiu dng, v1 v v2 l s hiu tng i ca chng (trn dng). Ging nh bi trc,
khong cch trong bi ny chnh l s TGV t nht, k cnh nhau trn ng i t TGV (d1,v1) n
TGV (d2,v2). Trc ht ta i ch hai ta , nu cn, sao cho tam gic th nht lun lun nm dng
trn so vi tam gic th hai, tc l d1 d2. Sau ta nhn xt nh sau:
Nu mt TGV c nh quay ln trn th
* S hiu tng i ca n l s l, v
* N s l nh ca mt tam gic u cha n v c cc cnh song song vi cc cnh ca bn c.
Nu mt TGV c nh quay xung di th
* S hiu tng i ca n l s chn, v
* TGV k cnh vi n trn cng dng s c nh quay ln trn.
Ta gi cc TGV c nh quay ln trn l tam gic l phn bit vi cc TGV chn - c nh
quay xung di.
Nu TGV th nht (d1,v1) l tam gic l ta xt tam gic ln hn to bi cc TGV nhn tam gic
l ny lm nh v c cnh y trn dng d2. Ta tnh hai nh trn y ca tam gic ny trn dng d2 l C1
v C2 theo cng thc
d := 2*(d2 - d1);
c1 := v1;
c2 := v1 + d;
Tip n ta xt v tr v2 trn cnh y c th nm gia C1 v C2 hoc nm ngoi oan [C1, C2]
ng thi xt v2 l tam gic chn hay l.
function KCLe(d1,v1,d2,v2: longint):longint;
var c1,c2,d: longint;
begin
{ v1 <= v2 }
d := 2*(d2 - d1);
c1 := v1;
c2 := v1 + d;
if (c1 <= v2) and (v2 <= c2) then
begin
if odd(v2) then KCLe := d
else KCLe := d - 1;
exit;
end;
KCLe := d + Min(abs(v2-c1),abs(v2-c2));
end;
Nu TGV th nht (d1,v1) l tam gic chn th ta li li mt dng d xt TGV l c chung y
vi TGDV th nht ri tnh ton nh trn v gim kt qu 1 n v.
function KhoangCach(d1,v1,d2,v2: longint):longint;
var t: longint;
begin
if d1 > d2 then
begin

119

t := v1; v1 := v2; v2 := t;
t := d1; d1 := d2; d2 := t;
end;
{ v1 <= v2 }
if odd(v1) then KhoangCach := KCLe(d1,v1,d2,v2)
else KhoangCach := KCLe(d1-1,v1-1,d2,v2) - 1;
end;
procedure XuLi;
var d,v,j: longint;
Ad, Av, Bd, Bv, Cd, Cv: longint;
begin
fillchar(kq,sizeof(kq),0);
ToaDo(NA, Ad, Av);
ToaDo(NB, Bd, Bv);
ToaDo(NC, Cd, Cv);
for d := 1 to N do
for v := 1 to 2*d - 1 do
inc(kq[Min3(KhoangCach(Ad,Av,d,v),
KhoangCach(Bd,Bv,d,v),
KhoangCach(Cd,Cv,d,v))]);
end;

Chng trnh C#
Chng trnh C# di y gii bi ton vi d liu cho trc N = 4, A, B v C ln lt xut pht ti
cc TGV 2, 14 v 9 nh th d cho.

// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao2 {
class TamGiacDeu {
static int n = 4, NA = 2, NB = 14, NC = 9;
static int[] Kq = new int[3];
static void Main(string[] args){
XuLi();
for (int i = 0; i < 3; ++i)
Console.Write(KQ[i] + " ");
Console.ReadLine();
}
// Tinh dong va vi tri tren dong
// theo so hieu cua TGDV
static void ToaDo(int cell, out int dong, out int viTri){
dong = 0;
while (cell > 0){
++dong; cell -= (2*dong - 1);
}
viTri = cell + (2*dong - 1);
}
static int KhoangCach(int d1, int v1, int d2, int v2){
if (d1 > d2){
int t;
t = d1; d1 = d2; d2 = t;
t = v1; v1 = v2; v2 = t;
}
return (v1%2==1)?KCLe(d1,v1,d2,v2):KCLe(d1-1,v1-1,d2,v2)-1;

120

}
static int KCLe(int d1, int v1, int d2, int v2){
int c1=v1, d=2*(d2-d1), c2=v1+d;
// Xet tam giac voi 3 dinh v1 c1 c2
if (c1 <= v2 && v2 <= c2)
return (v2 % 2 == 1) ? d : d-1;
return d + Math.Min(Math.Abs(v2-c1),Math.Abs(v2-c2));
}
static int Min3(int a, int b, int c){
int min = 0;
if (a > b) { min = 1; a = b;}
if (a > c) min = 2;
return min;
}
static void XuLi(){
int Ad, Av, Bd, Bv, Cd, Cv;
ToaDo(NA,out Ad, out Av);
ToaDo(NB,out Bd, out Bv);
ToaDo(NC,out Cd, out Cv);
Array.Clear(Kq, 0, Kq.Length);
for (int d = 1; d <= n; ++d){
int vv = 2*d-1;
for (int v = 1; v <= vv; ++v)
++KQ[Min3(KhoangCach(Ad,Av,d,v),
KhoangCach(Bd,Bv,d,v),
KhoangCach(Cd,Cv,d,v))];
}
}
} // Tam Giac Deu
} // SangTao2

phc tp
Ta phi duyt mi TGV trn bn c, vy phc tp tnh ton c N 2.

4.3 Dng biu din ca giai tha


Cho s t nhin n 480.000. Hy phn tch n! ra tch ca cc tha s nguyn t theo trt t tng
dn. Th d, 13! = 210.35.52.7.11.13. Kt qu hin th di dng cc dng, mi dng mt s nguyn t tip
n l s m tng ng. Cc s trn cng dng cch nhau qua du cch. Th d trn cho ta kt qu hin th
nh sau
2 10
3 5
5 2
7 1
11 1
13 1

Thut ton
Nhn xt Cho s t nhin N v mt s nguyn t p. Khi ,
Nu vit dy tha s 1, 2, ..., N vo mt bng c p ct th ta thy c n1 = N div p dng cha p,
2p,...,n1.p ( ct cui cng). Nhm cc phn t ny li ta c,
1p.2p....n1p = (1.2...n1).pn1. Thc hin tng t vi tch 1.2...n1 ta thu c n2 = n1 div p dng cha
p, 2p,...,n2.p... T y ta suy ra ly tha k ca p, p k trong dng phn tch ca N! s l k = n1+n2+...+nv, trong

121

ni = ni-1 div p, n1 = N div p, nv = 0, i = 2..v. Hm tnh ly tha ca p trong dng phn tch ca N! bng
cc php chia lin tip khi s nh sau,
function Power(n,p: longint): byte;
var k: byte;
begin
k := 0;
while (n <> 0) do
begin
n := n div p;
k := k + n;
end;
Power := k;
end;
Ta dng hm NextPrime sinh ln lt cc s nguyn t p trong khong 2..N v tnh
Power(N,p). Nu gi tr ny ln hn 0 th ta hin th kt qu.
procedure Fac(n: longint);
const bl = #32; { Dau cach }
var p: longint; k: byte;
begin
writeln;
p := 2;
while p <= n do
begin
k := Power(n,p);
if (k > 0) then writeln(p,bl,k);
p := NextPrime(p);
end;
end;
Hai hm ph tr.
Hm IsPrime(p) kim tra p c phi l s nguyn t hay khng bng cch xt xem trong khong
t 2 n

p c c no khng.

function IsPrime(p: longint): Boolean;


var i: longint;
begin
IsPrime := false;
if p < 2 then exit;
for i := 2 to round(sqrt(p)) do
if p mod i = 0 then exit;
IsPrime := True;
end;
Hm NextPrime(p) sinh s nguyn t st sau p bng cch duyt tun t cc s l sau p l p+2k
nu p l v (p-1) + 2k, nu p chn.
function NextPrime(p: longint): longint;
begin
if p < 2 then
begin
NextPrime := 2;
exit;
end;
if not odd(p) then p := p-1;
repeat
p := p+2;
until IsPrime(p);

122

NextPrime := p;
end;
Ta c th ci tin kh mnh tc tnh ton bng cc k thut sau.
Sinh sn cc s nguyn t trong khong t 1..N bng gii thut Sng mang tn nh ton hc Hi Lp
Eratosthene. T vi nghn nm trc, Eratosthenes dy nh sau:

Ba ging ca Eratosthenes

Eratosthenes (276-194 tr.


CN) Nh ton hc li lc Hy
Lp C i. ng sinh ti
Cyrene, theo hc trng phi
Plato ti Athens. Hong
Ptolemy II mi ng n
Alexandria dy cho hong
t.

Nu tr mun lit k ton b cc s nguyn t


nm trong khong t 1 n N hy lm nh sau
1. Vit dy s t 1 n N.
2. Xa i s 1 v n khng phi l s nguyn t, cng
khng phi l hp s. N l mt s c bit.
3. Ln lt duyt t 2 n N nh sau. Nu gp s
cha b xa th chnh l mt s nguyn t. Tr hy
xa mi bi ca s ny k t bnh phng ca n tr i.
Khi kt thc, nhng s no khng b xa trn tm
bng s l cc s nguyn t. l kho cc s nguyn t
trong khong 1..N.

Sau ng c giao ph trch th


vin Alexandria, mt trung tm lu tr
v bo tn cc tc phm vn ha v khoa
hc ni ting ng thi. Ngoi cc
cng trnh tan hc, Eratosthenes cn c
nhng ng gp rt gi tr v o lng.
ng tin hnh o kch thc Tri t.

Thi cha c giy vit nn thy tr phi vit trn nhng tm bng bng t st vo lc t cn
do, cc s b xa c c thng. Sau khi phi kh ta thu c nhng tm bng thng l ch nh mt ci
sng go.
Vi mng a[0..MN] of byte ln, th d, MN = 60.000 ta c th ghi nhn cc s nguyn t
nm trong khong 1..MN. Ta qui c a[i] = 0 th i l s nguyn t, a[i] = 1 ng vi s i b di thng nn i
khng phi l s nguyn t.
procedure Eratosthenes(n: longint);
var i,j: longint;
begin
fillchar(a,sizeof(a),0);
for i := 2 to round(sqrt(n)) do
if a[i]=0 then
for j := i to (n div i) do a[i*j] := 1;
end;
Th tc phn tch N! ra tha s nguyn t dng ci tin s nh sau,
procedure NewFac(n: longint);
const bl = #32; { Dau cach }
var i,p: longint;
begin
Eratosthenes(n);
writeln;
for i := 2 to n do
if a[i] = 0 then
begin
p := Power(n,i);
if P > 0 then writeln(i,bl,p);
end;

123

end;
Dng k thut nh du bit c th to kho s nguyn t c 8.MN v mt byte c 8 bit, mi bit s
qun l 1 s.
Mng a vn c khai bo nh trc: a[0..MN] of byte (quan trng l ch s phi tnh t 0
tr i) nhng lc ny mi phn t a[i] s qun l 8 s ch khng phi mt s nh trc. Tip n bn cn
vit thm ba th tc sau y:
Th tc BitOn(i) - t tr 1 cho bit th i trong dy bit a (bt bit). Cc bit trong dy a s c m
s t 0 n 8MN-1= 480.000-1. Bn thn s 480.000 l hp s nn ta c th b qua.
procedure BitOn(i: longint);
var b,p: longint;
begin
b := i shr 3; { i div 8 }
p := i and 7; { i mod 8 }
a[b] := a[b] or (1 shl p);
end;

t tr 1 cho bit i trong dy bit a


1. Xc nh xem bit i nm trong byte no
b := i div 8
2. Xc nh xem bit i l bit th my trong byte b
(tnh theo trt t 7,6,5,4,3,2,1,0)
p := i mod 8
3. Ly s nh phn 8 bit 00000001 dch tri p v
tr ri cng logic theo bit vi a[b].
a[b] := a[b] or (1 shl p);

Bn ghi nh s tng ng ca cc php ton sau y


Php ton tng ng

Php
ton
x
2k

div

x shr k

x
2k

mod

x and 2k-1
Tnh theo dng ny s nhanh
hn

Th tc BitOff(i) t tr 0 cho bit th i trong dy bit a (tt bit).


procedure BitOff(i: longint);
t tr 0 cho bit i trong dy bit a
var b,p: longint;
1. Xc nh xem bit i nm trong byte no
begin
b := i div 8;
b := i shr 3; { i div 8 }
p := i and 7; { i mod 8 }
2. Xc nh xem bit i l bit th my trong byte b
a[b]:=a[b] and (not(1 shl p)); (tnh theo trt t 7,6,5,4,3,2,1,0)
end;
p := i mod 8;
3. Ly s nh phn 6 bit 00000001 dch tri p v
tr, lt ri nhn logic theo bit vi a[b].
a[b]:=a[b] and (not(1 shl p));
Hm GetBit(i) cho ra tr (1/0) ca bit i trong dy bit a.
function GetBit(i: longint): byte;
var b,p: longint;

t tr 0 cho bit i trong dy bit a


1. Xc nh xem bit i nm trong byte no

124

begin
b := i shr 3;
p := i and 7; { i mod 8 }
GetBit := (a[b] shr p) and 1;
end;

b := i div 8;
2. Xc nh xem bit i l bit th my trong byte b
(tnh theo trt t 7,6,5,4,3,2,1,0)
p := i mod 8;
3. Dch a[b] qua phi p v tr, ri nhn logic
theo bit vi 00000001 ly bit phi nht (bit 0).
GetBit := (a[b] shr p) and 1;

Cc th tc c bn theo k thut x l bit khi s nh sau.


procedure Eratosthenes_B(n: longint);
var i,j: longint;
begin
fillchar(a,sizeof(a),0);
for i:=2 to round(sqrt(n)) do
for j:=i to (n div i) do
BitOn(i*j);
end;
procedure BFac(n: longint);
const bl = #32; { Dau cach }
var i,p: longint;
begin
Eratosthenes_B(n);
writeln;
for i:=2 to n do
if GetBit(i)=0 then
begin
p := Power(n,i);
if P > 0 then writeln(i,bl,p);
end;
end;

Chng trnh C#
//

C#

using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao2 {
class GiaiThua {
static byte [] a = new byte[40000];
static void Main(string[] args){
BFac(13);
Console.ReadLine();
}
static int Power(int n, int p){
int k = 0;
while (n != 0){ n /= p; k += n; }
return k;
}
static void Fac(int n) {
Console.WriteLine();
int p = 2, k;
while (p <= n){
k = Power(n,p);

125

if (k > 0) Console.WriteLine(p+" "+k);


p = NextPrime(p);
}
}
static bool IsPrime(int p){
if (p<2) return false;
if (p==2) return true;
if (p % 2 == 0) return false;
int cp = (int)(Math.Sqrt(p));
for (int i=3; i <= cp; i+=2)
if (p % i == 0) return false;
return true;
}
static int NextPrime(int p){
if (p < 2) return 2;
if (p % 2 == 0) --p;
do { p += 2; } while (!IsPrime(p));
return p;
}
// Sang Eratosthene dung byte
static void Eratosthenes(int n){
Array.Clear(a,0,a.Length);
int sn = (int)Math.Sqrt(n);
for (int i = 2; i <= sn; ++i)
if (a[i]==0){
int ni = n/i;
for (int j = i; j <= ni; ++j) a[i*j] = 1;
}
}
// Gan 1 cho bit i
static void BitOn(int i){
int b = i >> 3;
int p = i & 7;
a[b] |= (byte)(1 << p);
}
// Gan 0 cho bit i
static void BitOff(int i){
int b = i >> 3;
int p = i & 7;
a[b] &= (byte)~(1 << p);
}
// Lay tri cua bit i
static byte GetBit(int i) {
int b = i >> 3;
int p = (i & 7);
return (byte)((a[b] >> p)&1);
}
// Sang Eratosthene dung bit
static void Eratosthenes_B(int n){
Array.Clear(a, 0, a.Length);
int sn = (int)Math.Sqrt(n);
for (int i = 2; i <= sn; ++i)
if (GetBit(i) == 0) {
int ni = n / i;
for (int j = i; j <= ni; ++j) BitOn(i * j);
}
}

126

static void BFac(int n){


int p;
Eratosthenes_B(n);
for (int i = 2; i <= n; ++i)
if (GetBit(i)==0)
{
p = Power(n,i);
if (p > 0) Console.WriteLine(i+" "+p);
}
}
} // GiaiThua
} // SangTao2

phc tp
lit k cc s nguyn t t 1..N ta duyt t 1 n
c N cc bi ca chng. Vy phc tp tnh ton c N.

N , vi mi s nguyn t ta phi gch ti a

N.

4.4 Xp si
Cho mt bng chia li vung N dng m s 1..N tnh t trn xung v M ct m s 1..M tnh t
tri sang. Mi c php t khng qu 1 vin si. Ngi ta cho trc gii hn tng s si c php
t trn dng i l di, i = 1..N v trn mi ct j l Cj, j = 1..M. Hy tm mt phng n xp c nhiu si
nht trong bng, bit rng cc d liu u hp l v bi ton lun c nghim.

Thut ton
T chc d liu:
const MN = 101;
d: array[0..MN] of integer;
c: array[0..MN] of integer;
a: array[1..MN,1..MN] of byte;
trong d l mng cha gii hn si trn dng, c - trn ct, a l mng hai chiu biu din bng chia
li vung, a[i,j] = 1 - c vin si t ti dng i, ct j; a[i,j] = 0 - khng c si ti ny. Ta thc hin k
thut hai pha nh sau.
procedure XepSoi;
var j: integer;
begin
fillchar(a,sizeof(a),0);
d[0] := M+1; { dat linh canh }
{ Pha 1 } XepDong;
{ Pha 2 } for j := 1 to M do ChinhCot(j);
end;
Pha th nht: Xp ti a si vo mi dng. Mi dng i ta xp lin nhau d[i] vin si. ng thi ta s
dng li cc bin mng d v c vi ngha sau y: d[i] cho bit v tr ct ca vin si cui cng trn dng i.
c[j] cho bit s si cn c th xp thm trn ct j. D nhin, ta phi chnh li cc gi tr c[j] mi khi xp
thm 1 vin si vo ct ny. Nu c[j] < 0 tc l ta cn bt si ct j. Th tc xp dng khi s nh sau.
procedure XepDong;
var i,j: integer;
begin
for i := 1 to N do
for j := 1 to d[i] do
begin
a[i,j] := 1; dec(c[j]);
end;
end;

127

Pha th hai: Sau khi xp xong N dng ta tin hnh chnh tng ct j c gi tr c[j] < 0 n khi no
c[j] = 0. chnh ct j theo phng php tham lam ta duyt chn mt dng imin c cha si ti ct j v
u phi d[imin] t gi tr nh nht. Sau ta chuyn vin si trn dng imin t ct j sang ct d[imin]+1
v chnh li cc gi tr c[j] v d[imin]. tm dng imin ta cn dng phn t d[0] vi gi tr ln nht lm
phn t khi u. Ta c th cho gi tr ny l M+1, v mi dng khng th c qa M vin si. Bn cn lu
rng khi d[imin] = M tc l mi vin si cui cng trn mi dng u chim v tr ti ct M tc l ht ch
t si.
procedure ChinhCot(j: integer);
begin
while c[j] < 0 do GiamCot(j);
end;
procedure GiamCot(j: integer);
var i: integer;
begin
i := DongMin(j);
a[i,j] := 0; { Bo vien soi } inc(c[j]);
if d[i] = M then exit;
inc(d[i]); a[i,d[i]] := 1; { Dat 1 vien vao day }
dec(c[d[i]]);
end;
function DongMin(j: integer): integer;
var i,imin: integer;
begin
imin := 0;
for i:=1 to N do
if a[i,j]=1 then
if d[i] < d[imin] then imin := i;
DongMin := imin;
end;
Th d di y minh ha thut ton vi N = M = 4; d = (3,2,1,2), c = (2,2,2,2).
0

-2

-1

Cu hnh ban u

Sau Pha 1

-2

-1

-1

-2

-2

Chnh ct 1

128

-2

-1

-1

-2

Chnh ct 2
1

-2

-1

Chnh ct 3

phc tp
Ta cn chnh M ct. Mi ct ta cn lp ti a N ln, mi ln gim c 1 vin si trong ct.
gim 1 vin si ny ta phi duyt N dng tm imin. Tng cng ta cn c MN 2 thao tc.

Chng trnh C#
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao2 {
class XepSoi {
const int n = 4, m = 4;
static byte [,] a = new byte[n+1,m+1];
static int [] d = new int [n+1] {0,3,2,1,2};
static int [] c = new int [m+1] {0,2,1,2,3};
static void Main(string[] args) {
Xep(); Show();
Console.ReadLine();
}
static void Show(){
for (int i = 1; i <= n; ++i){
for (int j = 1; j <= m; ++j)
Console.Write(a[i, j]);
Console.WriteLine();
}
}
static void Xep(){
Array.Clear(a,0,a.Length);
d[0] = m+1;

129

XepDong();
for (int j = 1; j <= m; ++j) ChinhCot(j);
}
static void XepDong(){
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= d[i];++j){
a[i,j] = 1; --c[j];
}
}
static void ChinhCot(int j) {
while (c[j] < 0) GiamCot(j);
}
static void GiamCot(int j){
int i = DongMin(j);
a[i,j] = 0; // Bot 1 vien tai o (i,j)
++c[j];
if (d[i]==m) return; // het cho dat tren dong i
++d[i]; a[i,d[i]] = 1; // Dat 1 vien vao o (i,d[i])
--c[d[i]];
}
static int DongMin(int j){
int imin = 0;
for (int i = 1; i <= n; ++i)
if (a[i,j]==1)
if (d[i] < d[imin]) imin = i;
return imin;
}
} // XepSoi
} // SangTao2

4.5 Dy cc hon v
Dy cc hon v ca N ch ci HOA u tin trong bng ch ting Anh c sp theo trt t t
in tng dn v vit lin nhau thnh mt dy k t duy nht. Hy cho bit k t th M trong dy tnh t 1
tr i, 2 N 10, 1 M N.N!. Th d, vi N=3, ta c dy 6 hon v xp theo trt t t in l ABC, ACB,
BAC, BCA, CAB, CBA. Sau khi ghp chng ta thu c dy duy nht gm 18 k t
ABCACBBACBCACABCBA. K t th M = 15 trong dy l: B.

Thut ton
Nu ta vit mi hon v trn 1 dng th k t th M s nm trn dng d = (M-1) div N (tnh t dng
0) v s chim v tr v = ((M-1) mod N)+1 (tnh t 1) trn dng d . Nh vy ta cn xc nh hon v trn
dng d ri ly k t nm v tr v lm kt qu.
xc nh hon v (c1,c2,...,cN) ti dng d ta ln lt tnh cc k t ci, i = 1..N. Ta phn hoch cc
hon v theo nhm. Nu b k t u tin th ta cn li (N-1)! hon v, khi hon v ti dng d s ri vo
nhm d div (N-1)! v s chim dng d mod (N-1)! trong nhm . Tng t, ta tnh cho cc k t th 2, 3,
..., N-1. K t cn li s chim v tr th N. Nu bit nhm d ca k t th i trong hon v th ta tnh c
chnh k t nh sau.
d = 1 ng vi k t th nht trong s cc k t cha dng,
d = 2 ng vi k t th hai trong s cc k t cha dng,
...
Tng qut, d ng vi k t th d trong s cc k t cha dng.
Mi ln xc nh c k t no th ta nh du k t bng th tc Mark.
trnh vic tnh n! ta vit th tc ThuongDu(z, n, q, r) cho ra thng q v d r ca php chia s t
nhin z cho n!, c th l q = z div n! v r = z mod n!. Th tc ny kh n gin. Ta c

130

q1 = z div n; r1 = z mod n z = q1.n + r1;


q2 = q1 div (n-1); r2 = q1 mod (n-1) q1 = q2.(n-1) + r2;

qn-1 = qn-2 div 2; rn-1 = qn-2 mod 2 qn-2 = qn-1.2 + rn-1.


qn = qn-1 div 1 = qn-1; rn = qn-1 mod 1 = 0.
Thay ln lt cc i lng ca dng di vo dng trn ta thu c q = q n-1 v r = r1 + n.r2 + (n1).r3 ++ 3.rn-1 + 2.rn. Nhn xt ny cho php ta xy dng th tc theo k thut chia lin tip nh sau.
procedure ThuongDu(z,n: longint;var q,r: longint);
var c: longint;
begin
r := 0; q := z; c := 1;
while n > 1 do
begin
r := r + (q mod n)*c;
q := q div n;
c := n; n := n - 1;
end;
end;
Th tc Test trong chng trnh di y tnh mi xut hin ca cc k t (M = 1..24*4) trong dy
cc hon v vi N = 4.

Chng trnh Pascal


(* Pascal *)
uses crt;
const MN = 20; bl = #32;
var
b: array[0..MN] of byte;
{ d = z div n! r = z mod n! }
procedure ThuongDu(z,n: longint;var q,r: longint);
T vit
{ Danh dau ki tu v thu k
trong so cac ki tu chua dung }
procedure Mark(N,k,v: integer);
var i,d: integer;
begin
d := 0;
for i := 1 to N do
if b[i] = 0 then
begin
d := d+1;
if d = k then
begin
b[i] := v;
exit;
end;
end;
end;
{ Xac dinh ki tu thu M trong day cac hoan vi }
function Value(N: integer;M: longint): char;
var i,j,v: integer;
th,du,d: longint;
begin
fillchar(b,sizeof(b),0);
d := (M-1) div N; { Dong chua ki tu M }

131

v := (M-1) mod N + 1; { vi tri cua M tren dong d }


{ xac dinh hoan vi tai dong d }
j := N-1;
for i := 1 to N-1 do
begin
ThuongDu(d,j,th,du);
Mark(N, th+1,i);
j := j-1;
d := du;
end;
Mark(N,1,N);
for i:=1 to N do
if b[i] = v then
begin
Value := chr(ord('A') + i-1);
exit;
end;
end;
procedure Test;
var N: integer;
M: longint;
begin
N := 4; writeln;
for M := 1 to 24*N do
begin
write(Value(N,M));
if M mod N = 0 then
begin
if readkey = #27 then halt else writeln;
end;
end;
end;
BEGIN
Test;
END.

Chng trnh C#
// C#
using System;
using System.Collections.Generic;
using System.Text;
namespace SangTao2 {
class DayHoanVi {
const int MN = 20;
static int [] b = new int [MN+1];
static void Main(string[] args){
Test();
}
// q = z / n!; r = z % n!
static void ThuongDu(long z, int n,
out long q, out long r ){
q = z; r = 0;
int c = 1;

132

while
r
q
c
}

(n > 1){
+= (q % n) * c;
/= n;
= n; --n;

}
static void Mark(int n, long k, int v){
int d = 0;
for (int i = 1; i <= n; ++i)
if (b[i]==0){
++d;
if (d==k){ b[i] = v; return; }
}
}
static char Value(int n, long m){
Array.Clear(b, 0, b.Length);
long d = (int) (m - 1) / n;
// d - Dong chua ki tu can tim
int v = (int)(m - 1) % n + 1;
// v - vi tri cua ki tu tren dong d
int j = n - 1;
long th, du;
for (int i = 1; i < n; ++i){
ThuongDu(d, j, out th, out du);
Mark(n, th + 1, i);
d = du; --j;
}
Mark(n, 1, n);
for (int i = 1; i <= n; ++i)
if (b[i]==v) return (char)('A'+i-1);
return (char)0;
}
// test voi n=4, m=1..n.n!
static void Test(){
int n = 4;
int m4 = 24 * n;
string s;
for (long m = 1; m <= m4; ++m) {
Console.Write(Value(n, m));
if (m % n == 0){
s = Console.ReadLine();
if (s == "stop") break;
}
}
}
} // DayHoanVi
} // SangTao2

N
1
2
3
4

N!
1
2
6
24

N
1
1
1
2

N!
39916800
479001600
6227020800
87178291200

133

5 120
1 1307674368000
3
6 720
20922789888000
1
7 5040
355687428096000
4
8 40320
6402373705728000
1
9 362880
121645100408832000
5
1 362880
243290200817664000
1
0 0
0
6
1
7
1
8
1
9
2
0
Giai tha ca 20 s nguyn dng u
tin

Vi C# bn c th dng kiu int64 hoc long vi 64 bit (8 byte) biu din s nguyn trong khong
[-9.223.372.036.854.775.808, 9.223.372.036.854.775.807].

phc tp
Thut ton ch i hi N = 20 php chia cc s nguyn c ti a 20 ch s v gi th tc Mark N
ln, mi ln gi phi thc hin php duyt trn dy N phn t. Tng cng l N2 php ton, tc l c 400
php ton thay v 2432902008176640000 php ton nu ta sinh ln lt N! hon v bng phng php vt
cn vi N = 20.

4.6 B bi
Trn bn t mt b bi gm n-1 qun bi m s 1,2,,n-1, 3 n 10000. Trng ti ch nh bn
ly k qun bi. Sau trng ti a ra mt s t nhin s. Bn cn c gng thc hin t nht m thao tc
thuc mt trong hai loi sau y:
- Ly thm mt qun bi t trn bn,
- B bt mt qun bi trn tay,
cui cng t c h thc
t mod n = s mod n
(*)
trong t l tng s hiu cc qun bi c trn tay bn sau khi bn hon tt m thao tc nh trn.
D liu vo: file vn bn BAI.INP
Dng u tin: 3 s t nhin n, k v s.
T dng th hai tr i: k s t nhin th hin m s ca cc qun bi cn ly lc u.
D liu ra: Hin th trn mn hnh
Dng u tin: s t nhin m cho bit s thao tc t nht cn thc hin
Tip n l m dng, mi dng l mt thao tc ly thm hoc b bt mt qun bi v. v > 0 cho bit
cn ly thm (t trn bn) qun bi v; v < 0 cho bit cn bt (t trn tay) qun bi v t c h thc
(*).
Th d, vi n = 8, trng ti cho s s = 22 v ch nh bn ly k = 3 qun bi l 2, 3 v 6.

134

Nu bn b qun bi 2 v ly qun bi 5 th tng t = 3 + 6 + 5 = 14. Khi


t mod n = 14 mod 8 = 6 = s mod n = 22 mod 8.
Vy mt li gii cho b d liu ny l
Thc hin 2 thao tc: 2 v +5
BAI.INP

MN HNH

8 3 22
2 3 6

2
-2
5

NGHA
Cho b bi gm 8 qun. Lc u trng ti ch nh bn ly k = 3 qun bi
m s 2, 3 v 6. Ngoi ra trng ti a ra s s = 22.
Sau bn thc hin 2 thao tc
- b qun bi 2
- ly thm qun bi 5.
Khi tng s hiu cc qun bi c trn tay bn s l:
T = 3 + 6 + 5 = 14
T mod N = 14 mod 8 = 6 = s mod 8 = 22 mod 8.

5
n = 8; s = 22; Trn tay gi k = 3 qun bi 2, 3, 6.
Li gii: B qun bi 2, ly thm qun bi 5.
t = 3+6+5 = 14,
t mod 8 = 14 mod 8 = 6 = s mod 8 = 22 mod 8.

Thut ton
Ta s chng minh rng vi khng qu 2 thao tc (+) ly thm / () b bt mt qun bi ta c th t
c h thc (*).
Trc ht ta nhc li cc php ton ng d. Vi s nguyn dng n cho trc ta xt tp cc s d
trong php chia mt s t nhin x cho n, x mod n, Zn = {0,1,2,,n-1}. Trn Zn cc php ton cng v nhn
c thc hin nh bnh thng sau ly kt qu chia d cho n. Php ton ly s i ca s x cho ta nx.
Php tr xy c i thnh php cng x vi s i ca y. Ta c
Cng: (x + y) mod n

135

Nhn: x*y mod n


Ly s i ca x: n x
Tr: (x + (ny)) mod n.
Hy tng tng cc s ca Zn l 0, 1, , n-1 c b tr trn mt vng trn nh trn mt ng h.
tnh tng x+y ta xut pht t x v di chuyn y bc theo chiu kim ng h (cn gi l di chuyn xui),
mi bc ta chuyn qua mt s. Kt qu s l im dng cui cng. tnh hiu x y ta cng xut pht t
x v di chuyn y bc theo chiu ngc li (di chuyn ngc). rng, trn vng trn gm n s, di
chuyn xui y bc s cho cng kt qu nh di chuyn ngc (ny) bc, v ngc li, di chuyn ngc y
bc s tng ng nh di chuyn xui (ny) bc. iu ny c ngha l mun thm b n v cho i
lng t ta c th bt (nb) n v v ngc li, mun bt b n v t i lng t ta c th thm cho t (nb)
n v. Ta cng rng s hiu ca mi qun bi u nh thua n v mi qun bi hoc l c trn tay
ngi chi, hoc l nm trn bn. V l trn, i khi ngi ta ni tnh ton theo ng d (modulo) chnh l
tnh ton trn vng trn.
Bn cng cn ghi nh tnh cht sau y:
Vi mi s t nhin x, y v n, n > 0 v vi mi php ton s hc {+, ,*} ta lun c
(x y) mod n = ((x mod n) (y mod n)) mod n
Cng thc trn cho ta quy tc d hiu sau y: Khi tnh tr ca cc biu thc s hc ch cha cc
php ton cng, tr v nhn trong Zn ta c th thc hin php ly s d mod n trn cc hng t v cc kt
qu trung gian.
V ly tha nguyn dng tng ng vi php nhn lin tip, ta suy ra h qu sau:
ak mod n = (a mod n)k mod n
Sau khi bit cc gi tr input l n, k, s v s hiu cc qun bi cn ly ln tay, ta gn tr cho mng
a[1..n1] nh sau: a[i] = 1 cho bit qun bi i c trn tay, ngc li, a[i] = 0 cho bit qun bi i cn nm
trn bn. Vi th d cho, trng ti yu cu ta ly 3 qun bi c s hiu 2, 3 v 6 nn a = (0,1,1,0,0,1,0)
ng vi a[2] = a[3] = a[6] = 1, cc gi tr a[i] cn li u bng 0.
Trc ht ta tnh tng s hiu ca cc qun bi c trong tay lc u v t trong bin t. Sau ta
tnh t := t mod n v s := s mod n. Vi th d cho ta tnh c
t = 2+3+6 = 11, do t mod n = t mod 8 = 3
v s mod 8 = 22 mod 8 = 6
Tc l t = 3 v s = 6.
Gi s t s, ta t b = t s v xt cc trng hp loi tr nhau sau y:
1. b = 0: H thc (*) tha, ta khng phi lm g. Ta thng bo m = 0, trong m l s thao
tc +/ cn thc hin.
2. Qun bi b c trn tay, tc l a[b] = 1: Ta ch vic b qun bi ny xung, khi tng t s
gim b n v theo mod n.
3. Qun bi (nb) c trn bn, tc l a[nb] = 0: Ta ch vic ly thm qun bi ny. Khi tng
t s c thm (n-b) n v theo mod n, iu ny tng ng vi vic gim tng t i b n v theo mod n.
4. Nu khng xy ra cc trng hp 1, 2 v 3 nh trn, tc l b 0, a[b] = 0, a[nb] = 1, ta tin
hnh nh sau:
Tm hai qun bi u v v tha cc iu kin sau
Qun bi u c trn tay, a[u] = 1,
Qun bi v c trn bn, a[v] = 0,
u = (k*b) mod n; v = ((k1)*b) mod n, k l mt s t nhin. iu ny c ngha l u ln hn v b n
v theo mod n.
Nu tm c hai qun bi u v v nh trn ta s thc hin hai thao tc: b qun bi u (u) v ly
thm qun bi v (+v). Khi tng t s c gim mt lng b theo mod n. Tht vy,
(u v) mod n = (k*b (k1)*b) mod n = b.

136

Trng hp t < s ta phi thm b = s t n v cho cho t. Vic ny tng ng vi gim t bt (n-b)
n v. t b = n-b ri lp li th tc trn s cho ta kt qu tng ng.
Ta chng minh rng nu gp tnh hung 4 th bao gi cng c th tm c hai qun bi u v v nh
m t. Trn hai ngn nm trc nh ton hc C Hy Lp Diophantus pht biu v chng minh nh l
sau:
nh l Cho phng trnh ax mod n = b mod n, vi cc h s a, b, n l cc s t nhin, n > 0. Gi d
l c chung ln nht ca a v n, d = (a,n). Khi
a) Nu d khng l c ca b th phng trnh v nghim.
b) Nu b = kd th phng trnh c ng d nghim trong tp Zn. Cc nghim ny c dng (x +
i(n/d) ) mod n, trong x l mt nghim ty , i = 0,1,2...(d-1).
Phng trnh ax mod n = b mod n c ngi i sau gi l phng trnh Diophantus.
Chng minh
Nu x l nghim ca phng trnh ax mod n = b mod n th ax v b c cng s d theo mod n nn
hiu ca chng s chia ht cho n, ax b = kn, hay ax kn = b. Mt khc, do d = (a,n) nn a v n u chia
ht cho d v do hiu axkn cng chia ht cho d, th tc l b phi chia ht cho d. Gi s b = md tc l
phng trnh c nghim. Gi x l nghim nguyn khng m nh nht ca phng trnh trn, ta d dng
kim tra c rng x+i(n/d), i = 0,1,,(d1) cng l nghim ca phng trnh . Tht vy, ta rng
nu d l c chung ln nht ca a v n th an/d chnh l bi chung nh nht ca chng, ngha l an/d chia
ht cho a v n. Ta c
a(x+i(n/d)) mod n = ((ax mod n) + (i(an)/d) mod n) mod n
= (b mod n + 0) mod n = b mod n.
Ta chng minh xong.
Th d 1. Gii phng trnh sau
6x mod 9 = 21 mod 9
Phng trnh trn tng ng vi phng trnh sau:
6x mod 9 = 3
Ta c d = (6,9) = 3. V 3 l c ca v phi nn phng trnh cho c 3 nghim. D thy x = 2 l
mt nghim ca phng trnh. Vy cc nghim ca phng trnh di dng tng qut l
x + i(n/d) = 2 + i(9/3) = 2 + 3i, i = 0, 1, 2
C th l x1 = 2, x2 = 5 v x3 = 8 l 3 nghim trong tp Z9 = {0, 1, 2, 3, 4, 5, 6, 7, 8}.
Th d 2. Gii phng trnh
4x mod 12 = 5
Ta c, d = (4,12) = 4 khng phi l c ca 5. Phng trnh v nghim.
Tr li bi ton trn, khi gp tnh hung 4 ta c a[b] = 0 v a[nb] = 1. Xt phng trnh bx mod n
= (nb) mod n. V 1 b < n nn 1 nb < n v do (nb) mod n = nb, phng trnh cho c th vit
li l bx mod n = nb.
Theo tnh cht: c chung ln nht ca hai s t nhin (a,b) s khng i nu ta thay s ln nht
trong hai s bng hiu ca n vi s th hai, t d = (b,n), ta c d = (b,nb), tc l nb chia ht cho d,
do phng trnh bx mod n = nb lun c nghim. T nhn xt ny suy ra rng vng lp repeat trong
on trnh di y lun kt thc.
u := b;
repeat
v := u;
u := (u+b) mod n;
until a[u] = 1;
Tht vy, sau k ln lp ta thu c u = kb do phng trnh bx mod n = nb c nghim nn s tn ti
mt gi tr k u = kb mod n = nb. Do a[nb] = 1 nn ti a sau k ln lp th vng lp phi kt thc v ta
s thu c u = kb mod n. V v mang gi tr st trc ca u nn v = (k1)b mod n.
Ta c thut ton sau y

137

1. c d liu vo cc bin n, k v s
2. Khi tr cho mng a[1..n1] vi a[i] = 1 nu qun bi i c trn tay, a[i] = 0 nu qun bi i cn trn
bn.
3. Tnh t = tng s hiu cc qun bi c trn tay.
4. Tnh t := t mod n; s := s mod n.
5. Nu t s: t b := t s; ngc li t b := n (s t).
ngha: cn gim b n v t tng t t h thc
t mod n = s mod n
(*)
6. Xt cc trng hp loi tr nhau sau y
6.1 b = 0: t m = 0; Thng bo: Khng lm g; Stop.
6.2 a[b] = 1 (Qun bi b c trn tay):
Thng bo: Thc hin m = 1 thao tc b: B qun bi b; Stop.
6.3 a[b] = 0 v a[nb] = 0 (Qun bi b khng c trn tay, qun bi (n-b) c trn bn):
Thng bo: Thc hin m = 1 thao tc +(nb): Ly qun bi (nb); Stop.
6.4 a[b] = 0 v a[nb] = 1: (Qun bi b khng c trn tay, qun bi (n-b) khng c trn bn)
6.4.1 Tnh u v v
u := b;
repeat
v := u;
u := (u+b) mod n;
until a[u] = 1;
6.4.2 Thng bo: Thc hin m = 2 thao tc
u: B qun bi u
+v: Ly qun bi v.
6.4.3 Stop
T chng minh trn ta rt ra phc tp ca thut ton l O(n) v trong trng hp xu nht ta
duyt 1 ln mng a cha n-1 phn t.
T chc d liu:
const mn = 10000; { Max n }
bl = #32; { Du cch }
nl = #13#10; { New line: xung dng }
ESC = #27;
fn = 'bai.inp';
type mi1 = array[0..mn] of integer;
var a: mi1; { Dnh du cc qun bi }
n, k : integer; { n1: s lng qun bi }
{ k: s lng cc qun bi trn tay }
t , s: longint; { t: tng s hiu cc qun bi trn tay }
{ s: s i chng ca trng ti }
f: text; { input file }
Th tc c d liu: M input file, c cc gi tr n, k v s, c s hiu v nh du k qun bi c
chn. tnh tng t ca chng }
procedure Doc;
var i,j: integer;
begin
assign(f,fn); reset(f);
read(f,n,k,s);
t := 0; fillchar(a,sizeof(a),0);
for i := 1 to k do
begin
read(f,j); a[j] := 1; t := t+j;
end;
close(f);

138

end;
Th tc x l.
procedure XuLi;
var b,u,v: integer;
begin
t := t mod n; s := s mod n;
if t >= s then b := t-s else b := n-(s-t);
if (b = 0) then
begin
Ket(0,0,0);
exit
end;
if (a[b] = 1) then
begin { Quan bai b co tren tay }
Ket(1,-b,0); { bo xuong }
exit
end;
if (a[n-b] = 0) then
begin { Quan bai n-b co tren ban }
Ket(1,n-b,0); { Lay len }
exit
end;
{ Quan bai b khong co tren tay
Quan bai n-b khong co tren ban }
u := b;
repeat
v := u;
u := (u+b) mod n;
until (a[u] = 1);
Ket(2,-u,v); { bo u, lay v }
end;
Th tc Ket(m,u,v) thng bo kt qu ng vi cc trng hp:
m = 1: B bt hoc ly thm 1 qun bi u;
m = 2: B qun bi u, ly qun bi v.
procedure Ket(m,u,v: integer);
begin
case m of
0: write(nl,'Khong lam gi',nl);
1: begin
write(nl,' Thuc hien 1 thao tac: ');
if (u > 0) then write('+',u,nl)
else write(u,nl);
end;
2: begin
write(nl,' Thuc hien 2 thao tac: ');
if (u > 0) then write('+',u,bl)
else write(u,bl);
if (v > 0) then write('+',v,nl)
else write(v,nl);
end;
end;
end;
phc tp tnh ton: N.
Chng trnh C# di y hin th kt qu trn mn hnh.

139

Chng trnh C#
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao2 {
class BoBai {
const string fn = "bai.inp";
const int MN = 20;
static int[] a;
static int n; // so luong quan bai
static int k; // so luong quan bai tren tay
static int s; // so cho truoc trong khoang [1,n];
static int t;
static void Main(string[] args){
Doc(); XuLi();
Console.ReadLine();
}
static void Doc(){
int[] c =
Array.ConvertAll((File.ReadAllText(fn)).Split(
new char[] { '\0', '\n', '\t', '\r', ' ' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
n = c[0]; // so luong quan bai
k = c[1]; // so luong quan bai tren tay
s = c[2]; // so cho truoc
a = new int[n + 1];
Array.Clear(a, 0, a.Length);
t = 0;
for (int i = 3; i < c.Length; ++i){
a[c[i]] = 1; t += c[i];
};
}
static void XuLi(){
t %= n; s %= n;
int b = (t >= s) ? t - s : n - (s - t);
if (b == 0) { Ket(0, 0, 0); return; }
// Sua t: giam b don vi hoac tang n-b don vi
if (a[b] == 1) { // quan b co tren tay
Ket(1, -b, 0); // bo quan b
return;
}
if (a[n - b] == 0) { // quan n-b co tren ban
Ket(1, n - b, 0); // lay quan n-b
return;
}
// Quan b tren ban, quan n-b trn tay
int u = b, v = 0;
do { v = u; u = (u + b) % n; } while(a[u] == 0);
Ket(2, -u, v); // bo quan u, lay quan v
}
static void Ket(int c, int u, int v) {
switch (c){

140

case 0: Console.WriteLine(c); break;


case 1: Console.WriteLine(c + ": " + u); break;
case 2: Console.WriteLine(c + ": "+u+" , "+v);
break;
}
}
} // Bo Bai
} // SangTao2

4.7 Thun th
Dijkstra E.
Cho hon v a = (a1,a2,...,aN) ca N s nguyn dng u tin 1,2,...,N. Mt thun th ca a l dy b
= (b1,b2,...,bN) trong bi l s lng cc phn t nh thua a i v ng trc ai, bi = ||{aj | aj < ai, j < i}||.
Bit trc N, 2 N 1000.
a) Cho mt hon v a, tnh thun th b ca a.
b) Cho thun th b, tm han v a.
c) Mi thun th u c phn t u tin (tri nht) l 0 nn ta c th b phn t ny. Ngoi ra, nu
trong thun th cn c phn t 0 na ta b thm 1 phn t 0 thu c mt dy c M = N-1 hoc M = N2 phn t v gi dy ny l thun th thu gn c. Cho mt thun th thu gn. Hy tm hon v nh nht theo
trt t t in sinh ra thun th thu gn ny.
Th d, vi N = 5,
a) Cho a = (2,5,1,4,3) ta tnh c b = (0,1,0,2,2),
b) Cho b = (0,1,0,2,2) ta tm c a = (2,5,1,4,3),
c) Cho thun th thu gn c = (1,2,2), N = 5, ta tm c a = (2,3,5,4,1).
rng hai hon v (2,5,1,4,3) v (2,3,5,4,1) cng sinh ra thun th thu gn (1,2,2), nhng
hon v (2,3,5,4,1) nh hn.
D liu vo: text file THUANTHE.INP
Dng u tin: N
T dng th hai tr i: N phn t ca hon v a.
Dng tip theo: M
Trn cc dng tip theo: M phn t ca thun th thu gn.
D liu trn cng mt dng cch nhau qua du cch.
D liu ra: Hin th trn mn hnh theo trt t sau:
Cu a: Cho hon v a, tm thun th b.
Cu b: Cho thun th b, tm hon v a.
Cu c: Cho thun th thu gn c tm hon v nh nht a.
Thut ton
Vic xc nh thun th b t hon v a l d dng. Hai cu b v c l hi kh. Chng ta s s dng k
thut i xng trnh by mt thut ton do Dijkstra xut. Theo thut ton ny th th tc cho cu a v
b l i xng nhau. Thut ton tin hnh x l ti ch, ngha l khng s dng mng ph m trc tip bin
i hon v a thnh thun th lu lun trong a v ngc li.
Trc ht ta nhn xt rng vi hon v n v e = (1,2,...,N) th c ng e i phn t khng ln hn ei
v khng ng sau phn t ei, i = 1..N. Vy, nu trong mt hon v a m ta thy mt phn t a j ai v j i
th ta khng nh rng ch cn ng aj-1 phn t khng ln hn aj v khng ng sau phn t aj.
Ta khai bo cc bin x, y, a l cc mng cha cc hon v v thun th:
const MN = 1000;
type mi1 = array[0..MN] of integer;
var x,y,a: mi1;
Th tc bin i hon v a sang thun th a khi s nh sau:

141

procedure HoanViThuanThe(var a: mi1;n: integer);


var i,j: integer;
begin
for i := n downto 1 do
for j:=1 to i do
if (a[j] >= a[i]) then dec(a[j]);
end;
thu c hon v a t thun th a ta ch cn vit th tc x l theo chiu ngc li. Hai th tc
nh vy gi l i xng nhau.
procedure ThuanTheHoanVi(var a: mi1;n: integer);
var i,j: integer;
begin
for i := 1 to n do
for j := i downto 1 do
if (a[j] >= a[i]) then inc(a[j]);
end;
Hai th tc ny u c phc tp N2.
Cu c c gii nh sau. trc ht thm mt s 0 vo u tri ca d liu vo a. Sau xt hiu NM. Nu N-M=1 th chng t thun th thu gn a ch khuyt mt s 0. Ta ch vic gi th tc
ThuanTheHoanVi(a,N) l thu c kt qu. Trng hp N-M=2 th ta phi b thm mt s 0 na vo
mt v tr no trong a. Ta ln lt t s 0 ny vo u phi (v tr N) ri chuyn dn n v u tri, mi
ln mt v tr v gi th tc ThuanTheHoanVi sinh ra mt dy a[1..N] sau kim tra xem dy ny
c phi l hon v ca 1..N hay khng. Nu ng, ta dng thut ton v cho ra kt qu. kim tra mt dy
a[1..N] c phi l mt hon v ca 1..N ta s dng mt mng d[1..N] nh du xem mi phn t a[i] c xut
hin ng 1 ln hay khng. Tuy nhin trc ta phi kim tra iu kin 1 a[i] N m bo rng a[i]
nm trong gii hn ca ch s mng d.
procedure ThuanTheThuGon(var a: mi1; n,m: integer);
var b: mi1;
i: integer;
begin
move(a[1],a[2],m*sizeof(integer));
a[1] := 0; inc(m);
if (n = m) then
begin
ThuanTheHoanVi(a,n);
exit;
end;
b := a;
for i := n downto 2 do
begin
{ Them 0 tai vi tri i }
a := b;
move(a[i],a[i+1],(n-i)*sizeof(integer));
a[i] := 0;
ThuanTheHoanVi(a,n);
if LaHoanVi(a,n) then exit;
end;
end;
function LaHoanVi(var a: mi1; n: integer): Boolean;
var d: mi1;
i: integer;
begin
LaHoanVi := false;
fillchar(d,sizeof(d),0);
for i := 1 to n do

142

begin
if (a[i] < 1) or (a[i] > n) then exit;
if (d[a[i]] = 1) then exit;
d[a[i]] := 1;
end;
LaHoanVi := true;
end;

Chng trnh C#
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System;
namespace SangTao2 {
class ThuanThe {
const string fn = "thuanthe.inp";
const int MN = 1001;
static int[] a = new int[MN];
static int[] c = new int[MN];
static int n; // 1..n
static int m; // so luong phan tu trong thuan the thu gon
static void Main(string[] args){
Doc();
Console.WriteLine("\n n = " + n + " m = " + m);
Console.WriteLine("\n Cho Hoan vi: ");
Show(a, n);
HoanViThuanThe(a);
Console.WriteLine("\n Tim Thuan the: ");
Show(a, n);
Console.WriteLine("\n Cho Thuan the: ");
Show(a, n);
ThuanTheHoanVi(a);
Console.WriteLine("\n Tim Hoan vi: ");
Show(a, n);
Console.WriteLine("\n Cho Thuan the Thu gon: ");
Show(c,m);
ThuanTheThuGon(c);
Console.WriteLine("\n Tim Hoan vi: ");
Show(c, n);
Console.ReadLine();
}
static void Doc(){
int[] v =
Array.ConvertAll((File.ReadAllText(fn)).Split(
new char[] { '\0', '\n', '\t', '\r', ' ' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
int i = 0;
n = v[i++];
for (int j = 1; j <= n; ++j) a[j] = v[i++];
m = v[i++];
for (int j = 1; j <= m; ++j) c[j] = v[i++];
}
static void HoanViThuanThe(int[] a){
for (int i = n; i > 0; --i)

143

for (int j = 1; j <= i; ++j)


if (a[j] >= a[i]) --a[j];
}
static void ThuanTheHoanVi(int[] a){
for (int i = 1; i <= n; ++i)
for (int j = i; j > 0; --j)
if (a[j] >= a[i]) ++a[j];
}
static void ThuanTheThuGon(int[] c){
Array.Copy(c, 1, c, 2, m);
c[1] = 0; ++m;
if (m == n) { ThuanTheHoanVi(c); return; }
int [] b = new int [n+1];
Array.Copy(c,1,b,1,m);
for (int i = n; i >= 2 ; --i){
Array.Copy(b,1,c,1,i-1);
Array.Copy(b, i, c, i + 1, m - i + 1);
c[i] = 0;
ThuanTheHoanVi(c);
if (LaHoanVi(c)) return;
}
}
static bool LaHoanVi(int[] c){
int[] d = new int[n + 1];
Array.Clear(d,0,d.Length);
for (int i = 1; i <= n; ++i)
{
if (c[i] < 1 || c[i] > n) return false;
if (d[c[i]] > 0) return false;
d[c[i]] = 1;
}
return true;
}
static void Show(int[] a, int n){
for (int i = 1; i <= n; ++i)
Console.Write(a[i] + " ");
}
} // ThuanThe
} // SangTao2

phc tp
Th tc move(a,b,M) copy m byte t mng a sang mng b. Th tc ThuanTheThuGon c phc
tp N3 v n gi th tc ThuanTheHoanVi N ln. Hm kim tra mt dy a[1..N] c phi l hon v i hi
N thao tc v s dng mt mng ph d nh du cc phn t xut hin.

4.8 Cc nh khoa hc
Olimpic Quc t
Trong mt hi ngh khoa hc c n nh khoa hc (KH) t chc th gin di hnh thc sau. H t
mt my tnh trong cn phng hp, ngoi my ra ch c th cha thm 1 ngi, mn hnh my tnh hin s
0. Sau mi nh khoa hc buc phi thc hin n thao tc loi 1 v n thao tc loi 2 an xen nhau, trong
thao tc u tin phi l loi 1.
Thao tc loi 1: c

Thao tc loi 2: Ghi

144

Vo phng;
c v ghi nh s trn mn hnh;
Ra khi phng.

Vo phng;
Ly s nh trong u cng thm 1 v hin th
kt qu trn mn hnh;
Ra khi phng.

Khi hin th s mi trn mn hnh th s c trn mn hnh t ng b xa v ngi thc hin thao
tc loi 2 cng qun lun s nh.
Cho trc cc gi tr n v m. Hy b tr mt lch thc hin cc nh khoa hc hon thnh trn vn
cuc chi theo ng yu cu v s cui cng hin th trn mn hnh l m.
D liu vo: Tp vn bn KH.INP cha 2 s n v m trn mt dng cch nhau qua du cch.
D liu ra: Tp vn bn KH.OUT cha mt lch thc hin gm mt dy tun t cc dng lnh thuc
mt trong hai dng sau:
Dng th nht gm hai s t nhin ghi cch nhau qua du cch, i t cho bit nh khoa hc i thc
hin thao tc t; i {1,2,,n}; t {1,2}.
Dng th hai gm 4 s t nhin ghi cch nhau qua du cch, i t 1 t2 k cho bit nh khoa hc i thc
hin k ln lin tip cc thao tc t1 v t2 an xen nhau; i {1,2,,n}; t {1,2}; k > 0.
Nu khng c cch no b tr lch th ghi duy nht mt s 0.
Th d,
KH.INP

KH.OUT

3 4
1
3
1
2
1
2
2

1
1 2 3
2
1
1 2 2
2
1 2 2

ngha
C 3 nh khoa hc tham gia tr chi th gin vi nhim v sinh ra
kt qu trn mn hnh (MH) l s 4. Lch thc hin s nh sau:
Ngi s 1: c. MH = 0. u(1) = 0.
Ngi s 3: (c; Ghi) 3 ln. MH = 3.
Ngi s 1: Ghi. MH = u(1)+1 = 0+1 = 1.
Ngi s 2: c. u(2) = 1, MH = 1.
Ngi s 1: (c; Ghi) 2 ln. MH = 3.
Ngi s 2 Ghi. MH = u(2)+1 = 1+1 = 2.
Ngi s 2 (c;Ghi) 2 ln. MH = 2+2 = 4.
Ch thch: u(i) - s nh trong u nh khoa hc th i.

Thut ton
Ta s ch ra rng vi mi n 2 v mi m trong khong 2..n2 lun lun c mt lch tha yu cu ca
u bi (ta gi l lch hp l) mn hnh (MH) t gi tr m.
Sau khi m tp KH.INP v c hai gi tr n, m ta tin hnh xp lch v ghi dn kt qu vo tp
KH.OUT m sn. Trc ht ta nhn xt rng nu mt ngi thc hin lin tip k ln mt cp thao tc (c
- Ghi, vit tt l G), tc l sau 2k dng lnh
i 1
i 2
...
i 1
i 2
th gi tr ca MH c tng thm k n v. Dy 2k lnh trn c th vit gp li thnh mt lnh 4
thnh phn l i 1 2 k.

145

Ta tnh k = m div n v r = m mod n, ta c m = k.n+r , 0 r < n, vi ngha l t c gi tr m


trn MH th phi c k ngi thc hin y v lin tip n cp thao tc G, ngoi ra phi c t nht mt
ngi thc hin thm r cp thao tc G. Do yu cu mi ngi buc phi thc hin n thao tc v n thao
tc G, mt l t nhin, ta phi s dng 2 ngi ghi nhn gi tr hin c trn MH khi cn s tr li gi tr
(d nhin l phi cng thm 1) nhm m bo cho cc thao tc cn thit c thc hin lin tc. Xt 3
trng hp sau y.
Trng hp 1: r = 0, tc l m = k.n. Ta cn k ngi thc hin lin tip n cp thao tc G. Tuy
nhin, do nhng ngi khc cng phi thc hin y n cp thao tc G cho mi ngi, nn ta chia cc
thao tc thnh hai loi l cc thao tc v ch l nhng thao tc n mt thi im no s c mt thao tc
khc t li gi tr cho MH. Cc thao tc cn li c gi l thao tc c ch. Nh vy trng hp ny cn
c k ngi thc hin tng cng m = k.n cp thao tc c ch v mi thao tc cn li l v ch. Lch khi s
nh sau.
1 1 - Ngi s 1 c v nh s 0 trn mn hnh. u(1) = 0.
i 1 2 n ; i = k+1..n - Nhng ngi cn li (mang m s k+1..n) G n ln v ch.
1 2 - Ngi s 1 ghi s 1 ln mn hnh (c ch), MH = u(1)+1 = 0 + 1 = 1.
1 1 2 n-1 - Ngi s 1 G nt n-1 ln c ch, MH = n.
i 1 2 n ; i = 2..k - Nhng ngi s 2..k G n ln c ch, MH = n+(k-1).n = k.n = m.
Trng hp 2: r 0 v k > 0. Ta c m = k.n+r, 0 < r < n, k > 0. Trng hp ny cn n-1 ngi thc
hin cc thao tc v ch, 1 ngi thc hin r cp thao tc G c ch v cng chnh ngi phi thc hin
(n-r) cp thao tc v ch. Ta s dng 2 ngi , s 1 v s 2 nh sau.
1 1 - Ngi s 1 c v nh s 0. u(1) = 0.
i 1 2 n ; i = k+2..n - Nhng ngi m s t k+2 n n G n ln v ch.
1 2 - Ngi s 1 Ghi 1 ln MH. MH = u(1)+1 = 0 + 1 = 1.
2 1 - Ngi s 2 c v nh s 1. u(2) = 1.
1 1 2 n-r - Ngi s 1 G n-r ln v ch.
Tip n l nhng thao tc c ch:
2 2 - Ngi s 2 Ghi s 2 ln MH, MH = u(2)+1 = 1 + 1 = 2.
1 1 2 r-1 - Ngi s 1 G nt r-1 ln c ch, MH = 2+(r-1).
2 1 2 n-1 - Ngi s 2 G nt n-1 ln c ch, MH = 2+(r-1)+(n-1) = n+r.
i 1 2 n ; i = 3..k+1 - Nhng ngi s 3..k+1 G n ln c ch, MH = n+r+(k-1).n = k.n+r.
Trng hp 3: r 0 v k = 0, do m = r 2. Trng hp ny cn n-1 ngi thc hin cc thao tc
v ch, 1 ngi thc hin r cp thao tc G c ch v cng chnh ngi phi thc hin (n-r) cp thao tc
v ch. Ta s dng 2 ngi , s 1 v s 2 nh sau.
1 1 - Ngi s 1 c v nh s 0 trn MH. u(1) = 0.
i 1 2 n ; i = 3..n - Nhng ngi t s 3 n n G n ln v ch.
2 1 2 n-1 - Ngi s 2 G n-1 ln v ch.
1 2 - Ngi s 1 Ghi s 1 ln MH. MH = u(1)+1 = 0+1 = 1.
2 1 - Ngi s 2 c s 1 trn MH. u(2) = 1.
1 1 2 n-r+1 - Ngi s 1 G n-r+1 ln v ch.
2 2 - Ngi s 2 Ghi s 2 ln MH. MH = u(2)+1 = 1+1 = 2.
1 1 2 r-2 - Ngi s 1 G r-2 ln c ch, MH = 2 + (r-2) = r.
Phn di y trnh by cu trc d liu v cc th tc c v xp lch. Hai th tc ph tr Lenh2
v Lenh4 dng ghi mt lnh 2 tham bin dng i t v lnh 4 tham bin dng i t 1 t2 k vo output file g
KH.OUT. Trong cc ch thch di y d[i] l s trong u nh KH th i, t[i] l s thao tc G nh KH i
thc hin, MH mn hnh, k hiu MH = x cho bit ta khng quan tm n gi tr ca MH v sm mun
gi tr ny s b xa.
uses crt;
const

146

fn = 'kh.inp'; gn = 'kh.out';
bl = #32; nl = #13#10; mn = 100;
{ bl du cch; nl xung dng }
type
mi1 = array[0..mn+1] of integer;
var
f,g: text;
n, m, mh: integer;
d,t: mi1;
{ mh Mn hnh }
d[i] - so nho trong dau,
t[i] - con dem lenh cua nguoi i }
procedure Doc;
begin
assign(f,fn); reset(f);
read(f,n,m); close(f);
end;
procedure Lenh2(i,tt: integer);
begin writeln(g,i,bl,tt); end;
procedure Lenh4(i,tt1,tt2,k: integer);
begin if k > 0 then writeln(g,i,bl,tt1,bl,tt2,bl,k); end;
procedure XepLich;
var k,r,i: integer;
begin
assign(g,gn); rewrite(g);
if (n < 2) or (m < 2) or (m > n*n) then
begin writeln(g,0); close(g); exit; end;
k := m div n; { k nguoi co ich }
r := m mod n; { va r thao tac co ich }
if (r = 0) then
begin
Lenh2(1,1); {MH=0,d[1]=0,t[1]=1}
for i := k+1 to n do Lenh4(i,1,2,n);
{MH=x,t[i]=2n,i=k+1..n}
Lenh2(1,2); {MH=1}
Lenh4(1,1,2,n-1); {MH=n,t[1]=2n}
for i := 2 to k do Lenh4(i,1,2,n);
{ MH =n+(k-1)n=kn=m,t[i]=2n,i=2..k}
close(g); exit;
end;
{ r > 0 }
if k > 0 then
begin { r,k > 0 }
Lenh2(1,1); {MH=0,d[1]=0,t[1]=1}
{ Bo nhung nguoi vo ich }
for i:=k+2 to n do Lenh4(i,1,2,n);
{MH=x,t[i]=2n,i=k+2..n}
Lenh2(1,2); {1 Ghi;MH=1,t[1]=2}
Lenh2(2,1); {2 Doc;MH=1;d[2]=1,t[2]=1}
{ Cac thao tac vo ich cua 1 }
Lenh4(1,1,2,n-r); {MH=x,t[1]=2+2(n-r)=2(n-r+1)}
{ Tu day la cac thao tac co ich }
Lenh2(2,2); {MH=2,t[2]=2}
Lenh4(1,1,2,r-1);
{MH=2+r-1,t[1]=2(n-r+1)+2(r-1)=2n}
Lenh4(2,1,2,n-1);{MH=2+r-1+n-1=n+r,t[2]=2n}
for i := 3 to k+1 do Lenh4(i,1,2,n);

147

{MH=n+r+(k-1)n=kn+r=m,t[i]=2n,i=3..k+1}
close(g); exit;
end;
{ k = 0, r > 0 }
Lenh2(1,1); {1 Doc,d[1]=0,t[1]=1}
{ Bo nhung nguoi vo ich }
for i:=3 to n do Lenh4(i,1,2,n);{MH=x,t[i]=2n,i=3..n}
{ n-1 thao tac vo ich cua 2 }
Lenh4(2,1,2,n-1);{MH=x,t[2]=2(n-1)}
Lenh2(1,2); {1 Ghi,MH=1,t[1]=2}
Lenh2(2,1); {2 Doc,MH=1,d[2]=1,t[2]=2n-2+1=2n-1}
{ Cac thao tac vo ich cua 1 }
Lenh4(1,1,2,n-r+1);{MH=x,t[1]=2+2(n-r+1)=2(n-r+2)}
Lenh2(2,2); {MH=2,t[2]=2n}
Lenh4(1,1,2,r-2);{MH=2+r-2=r=m,t[1]=2(n-r+2)+2(r-2)=2n}
close(g);
end;
Bn c th vit thm th tc test kim tra xem lch xp v ghi trong tp KH.OUT c tha cc
yu cu ca u bi hay khng. Th tc s dng cc mng sau y. Mng d[1..n], d[i] l s nh trong u
ngi s i. Mng t[1..n], t[i] l s ln ngi th i thc hin cc thao tc c (1), Ghi (2). Do thao tc c
phi thc hin trc v hai thao tc c - Ghi phi an xen nn thi im st trc thao tc c ca ngi
th i ta phi c t[i] l s chn v thi im st trc thao tc Ghi phi c t[i] l s l. Mi ln c 1 dng
lnh th tc phi xt xem dng lnh cha 2 hoc 4 s. Th tc phi thc hin cc kim tra sau y.
Kim tra lnh dng i v: 1 i n, v = 1 hoc 2. Nu v = 1 th t[i] phi l s chn, nu v = 2 th t[i]
phi l.
Kim tra lnh dng i v1 v2 k: tng t nh trn.
Thc hin lnh i v: Nu v = 1 (thao tc c) th gn d[i] := MH; ngc li, nu v = 2 (ghi) th gn
MH := d[i] + 1. Trong c hai trng hp u tng con m lnh t[i] thm 1 n v.
Sau khi c xong tp KH.OUT phi duyt li cc con m m bo rng d[i] = 2.n vi mi i =
1..n. Cui cng kim tra xem MH = m?
procedure DocLenh(var i,t1,t2,k,v: integer);
begin
read(g,i,t1); v := 2;
if seekeoln(g) then exit;
readln(g,t2,k); v := 4;
end;
procedure XemLenh(i,t1,t2,k,KieuLenh: integer);
begin
if KieuLenh = 2 then writeln(i,bl,t1)
else writeln(i,bl,t1,bl,t2,bl,k);
end;
function Lenh(i,c: integer): Boolean;
begin
Lenh := false;
if (i < 1) or (i > n) then exit;
case c of
1: begin
if odd(t[i]) then exit;
inc(t[i]); d[i] := mh;
end;
2: begin
if not(odd(t[i])) then exit;
inc(t[i]); mh := d[i]+1;
end;

148

else exit;
end;
Lenh := true;
end;
function KiemTraLenh(i,t1,t2,k,v: integer): Boolean;
var j: integer;
begin
if v = 2 then KiemTraLenh := Lenh(i,t1)
else
begin
KiemTraLenh := false;
for j := 1 to k do
begin
if not Lenh(i,t1) then exit;
if not Lenh(i,t2) then exit;
end;
KiemTraLenh := true;
end;
end;
procedure Test;
var i,t1,t2,k,v,n2: integer;
begin
mh := 0;
fillchar(d,sizeof(d),0);
fillchar(t,sizeof(t),0);
assign(g,gn); reset(g);
while not Seekeof(g) do
begin
DocLenh(i,t1,t2,k,v);
XemLenh(i,t1,t2,k,v);
if not KiemTraLenh(i,t1,t2,k,v) then
begin
writeln('Sai '); close(g);
exit;
end;
end;
n2 := n+n;
for i:=1 to n do
if (t[i] <> n2) then
begin
writeln('Sai '); close(g);
exit;
end;
if (mh <> m) then
begin
writeln('Sai '); close(g);
exit;
end;
writeln('Dung');
close(g);
end;

Chng trnh C#
// C#
using System;

149

using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao2 {
class KhoaHoc {
const string fn = "KH.INP";
const string gn = "KH.OUT";
const int MN = 1002;
static int[] d = new int[MN]; // So nho trong dau
static int[] t = new int[MN]; // con dem thao tac
static int n; // nha khoa hoc
static int m; // man hinh cuoi
static int mh;
static StreamWriter g;
static StreamReader f;
static void Main(string[] args){
Run();
}
static void Run() { // Kiem tra tren 1 file
Doc();
Console.WriteLine("n = " + n + "
m = " + m);
XepLich();
Console.WriteLine("Output file " + gn);
Console.WriteLine(File.ReadAllText(gn));
Console.WriteLine("Now Testing...");
Test();
Console.ReadLine();
}
// Kiem tra file output KH.OUT
static void Test(){
f = File.OpenText(gn);
Array.Clear(d, 0, d.Length);
Array.Clear(t, 0, t.Length);
mh = 0;
int i, t1, t2, k, v;
while (DocLenh(out i, out t1, out t2, out k, out v)){
XemLenh(i, t1, t2, k, v);
if (!KiemTraLenh(i, t1, t2, k, v)){
Console.WriteLine("SAI LENH");
return;
}
}
f.Close();
for (int j = 1, nn = n + n; j <= n; ++j)
if (t[j] != nn){
Console.WriteLine("SAI SO THAO TAC" + t[j]);
return;
}
if (mh != m) Console.WriteLine("SAI KET QUA MH");
else Console.WriteLine(" LAP LICH DUNG "); }
static bool KTLenh2(int i, int tt){
switch (tt){
case 1: if (t[i] % 2 != 0) return false;
++t[i]; d[i] = mh; return true;
case 2: if (t[i] % 2 == 0) return false;

150

++t[i]; mh = d[i] + 1; return true;


default: return false;
}
}
static bool KiemTraLenh(int i, int t1, int t2,
int k, int v){
if (i < 1 || i > n) return false;
if (v == 2) return KTLenh2(i, t1);
for (int j = 1; j <= k; ++j){
if (!KTLenh2(i, t1)) return false;
if (!KTLenh2(i, t2)) return false;
}
return true;
}
static void XemLenh(int i, int t1, int t2, int k, int v)
{
if (v == 2) Console.WriteLine(i + " " + t1);
else Console.WriteLine(i+" "+t1+" "+t2+" "+k);
}
static bool DocLenh(out int i, out int t1,
out int t2, out int k, out int v){
i = t1 = t2 = k = v = 0;
if (f.EndOfStream) return false;
int[] c = Array.ConvertAll((f.ReadLine()).Split(
new char[] { '\t', ' ' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
foreach (int x in c) ++v;
Console.Write(" v = " + v + ": ");
if (v != 2 && v != 4) return false;
i = c[0]; t1 = c[1];
if (v == 4) { t2 = c[2]; k = c[3]; }
return true;
}
static void Doc(){
int[] v =
Array.ConvertAll((File.ReadAllText(fn)).Split(
new char[] { '\0', '\n', '\t', '\r', ' ' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
n = v[0]; // n nha khoa hoc
m = v[1]; // Gia tri man hinh
}
static void XepLich(){
g = File.CreateText(gn);
if (n < 2 || m < 2 || m > n * n){
g.WriteLine("0");
g.Close();
return;
}
int k = m / n;
int r = m % n;
Console.WriteLine("k = " + k + "
r = " + r);
if (r == 0){
Lenh2(1, 1);
for (int i = k + 1; i <= n; ++i)
Lenh4(i, 1, 2, n);

151

Lenh2(1, 2);
Lenh4(1, 1, 2, n - 1);
for (int i = 2; i <= k; ++i) Lenh4(i, 1, 2, n);
g.Close();
return;
}
if (k > 0){
Lenh2(1, 1); // 1 Doc
// Bo nhung nguoi vo ich
for (int i = k + 2; i <= n; ++i)
Lenh4(i, 1, 2, n);
Lenh2(1, 2); // 1 Ghi
Lenh2(2, 1); // 2 Doc
Lenh4(1,1,2,n-r);//cac thao tac vo ich cua 1
// Tu day la cac thao tac co ich
Lenh2(2, 2); // 2 Ghi
Lenh4(1, 1, 2, r - 1); // 1 DG r-1 lan
Lenh4(2, 1, 2, n - 1); // 2 DG n-1 lan
for (int i = 3, k1 = k + 1; i <= k1; ++i)
Lenh4(i, 1, 2, n);
g.Close();
return;
}
// k = 0
Lenh2(1, 1); // 1 Doc. Tu 3..n vo ich
for (int i = 3; i <= n; ++i) Lenh4(i, 1, 2, n);
Lenh4(2, 1, 2, n - 1);
Lenh2(1, 2); // 1 Ghi
Lenh2(2, 1); // 2 Doc
Lenh4(1,1,2,n-r+1); // Cac thao tac vo ich cua 1
Lenh2(2, 2); // 2 Ghi co ich
Lenh4(1, 1, 2, r - 2); // 1 Ghi not co ich
g.Close();
}
static void Lenh2(int
{ g.WriteLine(i + " "
static void Lenh4(int
if (k > 0)
g.WriteLine(i + "
}
} // KhoaHoc
} // SangTao2

i, int t)
+ t); }
i, int t1, int t2, int k) {
" + t1 + " " + t2 + " " + k);

phc tp
Thut ton pht sinh v ghi vo file kt qu ti a 2.n2 dng lnh.

4.9 Chn chic ng h


Olimpic Quc t
C 9 chic ng h in t treo trn mt bng theo s 3 3. Cc ng h c m s t 1 n 9
theo trt t t tri qua phi, t hng trn xung hng di. Mi ng h c 4 im ch gi ng vi cc gi
12, 3, 6 v 9. Gi hin tr ca mi ng h ng vi im sng . iu khin cc ng h ngi ta s
dng 9 phm vi cc chc nng c m t nh trong hnh v. Khi nhn vo mt phm th c 4 ng h
ng lot nhy im sng i 90o theo chiu kim ng h cng thm 3 gi tnh t gi hin tr. Th d, khi
nhn phm 1 th 4 ng h 1, 2, 4 v 5 s c chnh gi theo lut trn. Bit gi hin ti ca cc ng h.
Hy xc nh mt dy ngn nht cc phm cn nhn cc ng h ng lot tr 12 gi.

152

6h

9h

3h

12h

12h

S b tr
9 ng h

9h

9h

6h

6h

9 ng h, gi ang tr

9 phm
iu khin
1

D liu vo: tp vn bn DONGHO.INP gm 12 dng


3 dng u tin gm 9 s tr gi ti thi im u b tr theo ma trn 3 3.
Dng th i trong s 9 dng tip theo, i = 1, 2, 3, 4 ghi 4 s t nhin th hin m s ca 4 ng h s
nhy im sng 90o khi ta nhn phm i.
Cc s trn cng dng cch nhau qua du cch.
D liu ra: Tp vn bn DONGHO.OUT gm hai thng tin:
- Bi ton c nghim (ghi s 1) hoc v nghim (ghi s 0).
- Dy phm ngn nht cn nhn cho trng hp c nghim.
DONGHO.INP
9 6 9
9 12 3
12 6 6
1 2 4 5
2 3 5 6
4 5 7 8
5 6 8 9
1 2 3 5
1 4 5 7
3 5 6 9
5 7 8 9

DONGHO.OUT
1
1 2 4 4

153

2 5 6 8
ngha: Nhn ln lt cc phm 1, 2, 4,
4
c 9 ng h u ng lot tr 12 gi.

Thut ton
Ta nhn thy rng do cc ng h hot ng c lp vi nhau nn dy phm cn nhn l giao hon,
ngha l c th lit k dy phm theo trt t ty . Th d, nhn cc phm 1, 2, 3 s mang li kt qu nh
khi nhn dy phm 2, 1, 3 hoc theo bt k hon v no ca 3 phm . Ngoi ra, nu mt phm c nhn
n mt bi ln ca 4 th im sng tr gi s quay li ng v tr ban u, do ta khng di g m nhn
mt phm qa 3 ln. T hai nhn xt trn ta thy rng c th dng k thut vt cn, c th l xt cc t hp
dy phm p[1..9], p[i] = 0..3 biu th s ln bm phm i. Vi mi t hp p ta tnh xem cc ng h c cp
nht ra sao. Nu c 9 ng h u nhy v thi im 12 gi th ta chn phng n c s ln bm phm t
nht trong s cc t hp ng vin.
Di y l mt vi chi tit s dng trong
chng trnh. Ta khi to sn mng hai chiu m t
chc nng ca cc phm iu khin, phim[i,j] cho
bit khi nhn phm i th ng h j s c chnh.
var
phim: array[1..9,1..4] of
integer;
Sau khi c d liu ng vi th d c th th
mng phim s c gn tr nh sau:
phim = ((1,2,4,5),
(2,3,5,6),
(4,5,7,8),
(5,6,8,9),
(1,2,3,5),
(1,4,5,7),
(3,5,6,9),
(5,7,8,9),
(2,5,6,8));
Bn cng nn m t sn mt kiu mng 9 phn
t biu th cc phm v cc ng h.
type mi1 = array[1..9] of
integer;
var
dongHo: mi1;
f: text;
imin, imax: longint;

Bn c th s dng 9 vng for lng nhau ng


vi 9 phm, mi vng bin thin t 0 n 3 ng vi s
7
8
9
ln nhn phm.
Bin ts dng tnh tng s ln nhn phm. D
thy, mi phm c nhn ti a 3 ln, vy 9 phm s
Chc nng ca cc phm iu khin
c nhn ti a 9.3 = 27 ln. Ta ly 28 lm ga tr
khi u cho vic tnh tsmin - tng s ln nhn phm t nht. Ta cng nn chuyn cc s trn mt ng h
l (12,3,6,9) sang cc s h 4 l (0,1,2,3) cho tin tnh ton. Hm Sum(p) tnh tng 9 phn t ca mng p
- chnh l tng s ln nhn phm ca phng n p. Hm KiemTra(q) thc hin vic kim tra xem 9 ng
h c cng tr n 12h hay khng, q[i] l s ln ng h i c cp nht khi thc hin phng n p.

154

Bn cng c th s dng h 4 x l nh sau: Cc phng n nhn 9 phm bin thin t


(0,0,0,0,0,0,0,0,0) n (3,3,3,3,3,3,3,3,3) ng vi imin = 0 v imax = 4 9-1 = 218-1 = (1 shl 18) - 1 =
262143. Ta cho i bin thin t imin n imax. Vi mi i ta xy dng phng n nhn phm bng cch gi
th tc Split(i,p) chuyn s i sang dng biu din h 4 ghi vo mng p, trong p[j] s l s ln nhn
phm j. Bit p ta d dng cp nht cc ng h.
Chng trnh di y ci t 2 phng n vt cn, Run1 chn vng for lng nhau v Run2 - tnh
ton theo h 4.

(* Pascal *)
(* Dong ho *)
const bl = #32; fn = 'DONGHO.INP'; gn = 'DONGHO.OUT';
type mi1 = array[1..9] of integer;
var
dongHo,kq: mi1;
f,g: text;
imin, imax: longint;
s, tsmin: integer;
var
phim: array[1..9,1..4] of integer;
procedure Split(x: longint; var a: mi1);
var i: integer;
begin
for i := 1 to 9 do
begin
a[i] := x mod 4;
x := x div 4;
end;
end;
procedure Doc;
var i,j: integer;
begin
assign(f,fn); reset(f);
for i:=1 to 9 do read(f,dongHo[i]);
for i:=1 to 9 do
for j:=1 to 4 do read(f,phim[i,j]);
close(f);
end;
procedure Ghi;
var i,j: integer;
begin
assign(g,gn); rewrite(g);
if tsmin = 28 then writeln(g,0) { vo nghiem }
else
begin { co nghem }
writeln(g,1);
for i := 1 to 9 do
for j := 1 to c[i] do write(g,i,bl);
writeln(g);
end;
close(g);
end;
procedure Init;
var i: integer;
begin
for i:=1 to 9 do dongHo[i] := (dongHo[i] div 3) mod 4;
imin := 0;

155

imax := 1;
imax := (imax shl 18 - 1);
end;
function KiemTra(var q: mi1): Boolean;
var i: integer;
begin
KiemTra := false;
for i:=1 to 9 do
if (dongHo[i]+q[i]) mod 4 <> 0 then exit;
KiemTra := true;
end;
function Sum(var q: mi1): integer;
var i,s: integer;
begin
s := 0;
for i:=1 to 9 do s := s+q[i];
Sum := s;
end;
procedure XuLiFor;
var j,k,ts: integer;
q,p: mi1; { p[i] so lan nhan phim i }
i,ikq: longint;
begin
tsmin := 28; { = 3*9+1 }
for p[1] := 0 to 3 do
for p[2] := 0 to 3 do
for p[3] := 0 to 3 do
for p[4] := 0 to 3 do
for p[5] := 0 to 3 do
for p[6] := 0 to 3 do
for p[7] := 0 to 3 do
for p[8] := 0 to 3 do
for p[9] := 0 to 3 do
begin
fillchar(q,sizeof(q),0);
for j := 1 to 9 do
begin
for k := 1 to 4 do
inc(q[phim[j,k]],p[j]);
end;
if KiemTra(q) then
begin
ts := Sum(p);
if ts < tsmin then
begin
tsmin := ts;
kq := p;
end;
end;
end;
end;
procedure XuLi;
var j,k,ts: integer;
q,p: mi1;
i,ikq: longint;
begin
tsmin := 28; { = 3*9+1 }

156

for i:=imin to imax do


begin
Split(i,p); { bam phim j p[j] lan }
fillchar(q,sizeof(q),0);
for j := 1 to 9 do
begin
for k := 1 to 4 do
inc(q[phim[j,k]],p[j]);
end;
if KiemTra(q) then
begin
ts := Sum(p);
if ts < tsmin then
begin
tsmin := ts;
ikq := i;
end;
end;
end;
Split(ikq,kq);
end;
procedure Run1;
begin
Doc; Init;
XuLiFor; Ghi;
end;
procedure Run2;
begin
Doc; Init;
XuLi; Ghi;
end;
BEGIN
Run1;
END.

Chng trnh C#
// C#
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace SangTao2 {
class DongHo {
const string fn = "DONGHO.INP";
const string gn = "DONGHO.OUT";
const int cc = 9;
static int[,] phim = new int [9,4];
static int[] dongHo = new int[cc];
static int [] kq = new int [cc];
static int smin = 0; // Tong so lan nhan phim
static void Main(string[] args) {
Run2();
Console.ReadLine();
}
static void Run1(){

157

Doc(); Init(); XuLi(); Ghi(); XemKq();


}
static void Run2(){
Doc(); Init();
XuLiFor(); Ghi(); XemKq();
}
static void XuLiFor(){
int [] p = new int [cc];// 9 phim
int[] dh = new int[cc];//so lan nhay kim cua 9 DH
int s = 0;
smin = 28;
for (p[0]=0; p[0] < 4; ++p[0])
for (p[1]=0; p[1] < 4; ++p[1])
for (p[2]=0; p[2] < 4; ++p[2])
for (p[3]=0; p[3] < 4; ++p[3])
for (p[4]=0; p[4] < 4; ++p[4])
for (p[5]=0; p[5] < 4; ++p[5])
for (p[6]=0; p[6] < 4; ++p[6])
for (p[7]=0; p[7] < 4; ++p[7])
for (p[8]=0; p[8] < 4; ++p[8]){
Array.Clear(dh,0,dh.Length);
for (int j = 0; j < cc; ++j)
//phim j nhan p[j] lan
for (int k = 0; k < 4; ++k)
// 4 DH chuyen kim
dh[phim[j, k]] += p[j];
if (KiemTra(dh)){
s = Sum(p);
if (s < smin){
smin = s;
p.CopyTo(kq,0);
}
}
}
}
static int Sum(int []p){ // Tong so lan nhan phim
int s = 0;
for (int i = 0; i < cc; ++i) s += p[i];
return s;
}
static void Doc() { // Doc du lieu tu input file
int[] v =
Array.ConvertAll((File.ReadAllText(fn)).Split(
new char[] { '\0', '\n', '\t', '\r', ' ' },
StringSplitOptions.RemoveEmptyEntries),
new Converter<String, int>(int.Parse));
int k = 0;
for (int j = 0; j < cc; ++j) dongHo[j] = v[k++];
for (int i = 0; i < cc; ++i)
for (int j = 0; j < 4; ++j)
phim[i, j] = v[k++];
}
static void Init() { // Khoi tri
for (int j = 0; j < cc; ++j)
dongHo[j] = (dongHo[j] / 3) % 4;
for (int i = 0; i < cc; ++i)
for (int k = 0; k < 4; ++k)

158

--phim[i, k];
}
static void XuLi(){
int imax = ((int)1 << 18) - 1;
int[] p = new int[cc]; smin = 28;
int[] q = new int[cc];
for (int i = 0; i <= imax; ++i){
int s = Split(i, p);
Array.Clear(q, 0, q.Length);
for (int j = 0; j < cc; ++j)
for (int k = 0; k < 4; ++k)
q[phim[j, k]] += p[j];
if (KiemTra(q))
if (s < smin){ smin = s; p.CopyTo(kq,0); }
}
}
static void Ghi(){
StreamWriter g = File.CreateText(gn);
if (smin < 28) { // co nghiem
g.WriteLine(1);
for (int i = 0; i < cc; ++i)
for (int j = 1; j <= c[i]; ++j)
g.Write((i + 1) + " ");
}
else g.WriteLine(0); // vo nghiem
g.Close();
}
static bool KiemTra(int[] q)// Kiem tra ca 9 DH tro ve 0?
{
for (int i = 0; i < cc; ++i)
if ((dongHo[i] + q[i]) % 4 > 0) return false;
return true;
}
// Tach x thanh cac chu so he 4 va tinh tong
static int Split(int x, int[] p){
int s = 0;
for (int i = 0; i < cc; ++i)
{ p[i] = x % 4; s += p[i]; x /= 4; }
return s;
}
static void XemKq(){
Console.WriteLine("\n Input file " + fn);
Console.WriteLine(File.ReadAllText(fn));
Console.WriteLine("\n Output file " + gn);
Console.WriteLine(File.ReadAllText(gn));
}
} // DongHo
} // SangTao2

4.10 S duy nht


Olimpic Baltics
Tp vn bn UNIQUE.INP cha dy s, mi s chim mt dng di khng qu 20 ch s. Trong
dy ny c duy nht mt s xut hin ng mt ln, cc s cn li u xut hin ng k ln. Hy tm s duy
nht . S k khng cho trc, nhng bit rng l mt s chn khc 0. Kt qu hin th trn mn hnh.

159

Thut ton
Ta da vo mt kin thc c t hng ngn nm trc, l biu din s theo v tr. Ta ln lt c
tng dng vo mt bin string sau ghi vo mt mng a s ln xut hin ca tng ch s ti tng v tr,
a[c,i] cho bit s ln xut hin ca ch s c ti ct i tnh t tri qua phi.
Vi th d cho, trn ct 1 ta tnh c a[1,1] = 5, a[2,1] = 4, a[3,1] = 0,... , a[8,1] = 4...
Nh vy mng a c kch thc 10 hng cha 10 ch s 0..9 v 20 ct cha cc ch s di nht.
Sau khi c xong d liu, ta thy mi phn t ca mng a hoc l chia ht cho k do l s chn, hoc l
s l c dng m.k + 1, m = 0, 1, 2,... Nu a[c,i] l s l th c s l ch s xut hin ti ct i ca s duy nht
cn tm.

Chng trnh Pascal


(* Pascal *)
procedure XuLi;
const mn = 20;
ChuSo = ['0'..'9'];
fn = 'unique.inp';
var a: array['0'..'9',1..mn] of integer;
f: text;
i: integer;
s: string;
cs: char;
begin
fillchar(a,sizeof(a),0);
assign(f,fn); reset(f);
while not seekeof(f) do
begin
readln(f,s);
for i:=1 to length(s) do
if s[i] in ChuSo then inc(a[s[i],i]);
end;
close(f);
s := ''; { Ket qua }
for i := 1 to mn do
for cs := '0' to '9' do
if Odd(a[cs,i]) then s := s+cs;
writeln(s);
end;
BEGIN
XuLi;
readln;
END.

UNIQUE.IN
P

MN HNH

1357
2008
80
1357
2008
80
2008
1357
10203040
80
2008
80
1357

10203040

Gii thch: S duy nht cn tm


l 10203040. Cc s cn li
u xut hin 4 ln.

Chng trnh C#
// C#
using
using
using
using
using

System;
System.Collections.Generic;
System.Linq;
System.Text;
System.IO;

160

namespace SangTao2 {
class Unique {
const string fn = "UNIQUE.INP";
static void Main(string[] args){
Console.WriteLine(XuLi());
Console.ReadLine();
}
static string XuLi(){
string s;
StreamReader f = File.OpenText(fn);
int mn = 20;
int [,] a = new int[10,mn];
Array.Clear(a, 0, a.Length);
while (true){
s = f.ReadLine().Trim();
if (s.Length == 0) break;
for (int i = 0; i < s.Length;++i)
if (s[i] >= '0' && s[i] <= '9')
++a[s[i]-'0',i];
}
f.Close();
string kq = "";
for (int i = 0; i < mn; ++i)
for (int cs = 0; cs <= 9; ++cs)
if (a[cs, i] % 2 == 1)
kq += cs;
return kq;
}
} // Unique
} // SangTao2

phc tp
Nu c n s di ti a m ch s th ta cn xt mi ch s 1 ln, ngha l tng cng cn n.m thao tc.
Duyt mng a cn 10.m thao tc l s rt nh so vi n.m.

Cc bin th ca bi UNIQUE
1. Nu u bi cho bit s k th khng cn i hi k l s chn.
2. Bit duy nht mt s xut hin ng m ln, cc s cn li u xut hin k ln nh nhau, k m v
k v m nguyn t cng nhau. Bn th suy ngh xem c cn bit c th cc gi tr ca m v k khng? Bn
th tm mt s iu kin ca k v m?
3. Thay cc s bng cc dy k t A..Z di ti a m.
________________________
21.01.2010
NXH

161

You might also like