Chuyên đề bồi dưỡng HSG Tin học
Trang 1CHUYÊN ĐỀ BỒI DƯỠNG HSG TIN HỌC
SỐ HỌC
I Chuyển đổi hệ cơ số:
Trong hệ thập phân:
Các con số được biểu diễn bởi 10 chữ số từ 0…9.
Cách biểu diễn số thập phân: anan-1….a2a1a0 (0<=a<=9)
Giá trị được tính: an.10n +an-1.10n-1 +… +a2.102 + a1.101 + a0.100
Trong hệ cơ số k:
Cách biểu diễn số trong hệ cơ số k: anan-1….a2a1a0 (0<=a<=k-1)
Trong đó nếu k>10 được biểu diễn bởi các chữ cái từ A -> Z
Giá trị được tính: an.kn +an-1.kn-1 +… +a2.k2 + a1.k1 + a0.k0
Bài 1.1 Nhập vào từ bàn phím số nguyên a (a>0) và số nguyên k (2<=k<=36).
Hãy viết chương trình chuyển đổi từ a trong hệ thập phân (hệ cơ số 10) sang hệ
cơ số k?
uses crt;
var a:qword;n,m:longint;k,i,j:byte;
kq,st:string;
function cdcs(x:qword;y:byte):string;
begin
kq := ''; n:=x;
while n<>0 do
begin
if n mod y <10 then st:= chr(48 + n mod y)
else if n mod y <= 36 then st:= chr(55 + n mod y);
kq := st + kq;
n := n div y;
end;
cdcs := kq;
end;
begin
write('Nhap a va co so k(2<=k<=36): '); readln(a,k);
write (a,'(10) = ',cdcs(a,k),'(',k,')');
readln;
end
Bài 1.2 Nhập vào từ bàn phím một số nguyên k (2<=k<=36) và một số a được
biểu diễn trong hệ cơ số k Hãy viết chương trình chuyển đổi a trong hệ cơ số k sang hệ thập phân (hệ cơ số 10)?
uses crt;
var a:string;k,i:byte;
function lt(k,m:longint):longint;
var i:byte;
begin
lt := 1;
for i := 1 to m do lt:=lt*k;
end;
function cdcs(s:string;y:byte):longint;
var kq,n,i:word;
Trang 2kq := 0; n := length(s);
for i:= n downto 1 do
if (ord(s[i])- 48) < 10 then kq:=kq+(ord(s[i])-48)*lt(y,n-i)
else if (ord(s[i])-55 >= 10) then kq:=kq+(ord(s[i])-55)*lt(y,n-i);
cdcs := kq;
end;
begin
write('Nhap so a va co so k: '); readln(a,k);
write(a,'(',k,') = ',cdcs(a,k),'(10)');
readln;
end
II Phân tích số:
Cách thực hiện:
- Sử dụng phép chia lấy số dư (mod) khi chia cho 10 ta được chữ số hàng đơn
vị
- Sử dụng phép chia lấy phần nguyên (div) khi chia cho 10 để bỏ đi chữ số hàng đơn vị Ta được số có số chữ số giảm đi 1, cứ như vậy cho tới khi không còn số nào.
Bài 2.1 Viết chương trình in ra màn hình tổng các chữ số của số nguyên n
(0<=n<=1015) được nhập vào từ bàn phím:
Ví dụ: Khi nhập N=357 chương trình sẽ tính tổng các chữ số là 3+5+7 = 15 và
in 15 ra màn hính.
Dữ liệu vào: 357
Dữ liệu ra: 15
uses crt;
var n:int64;i,j,s:byte;
a:array[1 20] of byte;
begin
clrscr;
write('Nhap so n: ');readln(n);
i:=1;
while n<>0 do
begin
a[i]:=n mod 10; n:=n div 10; i:=i+1
end;
s:=0;
for j:=i-1 downto 1 do s:=s+a[j];
Writeln('Tong la:',s);
readln
end.
Nhận xét: Tạo mảng A để lưu các chữ số của N từ chữ số hàng đơn vị đến hết Dùng phép chia dư mod để được các chữ số hàng đơn vị lưu vào A, dùng phép chia nguyên div để xoá chữ số hàng đơn vị sau khi đã lưu.
Trang 3uses crt;
var n:string;i,k,s:byte;
begin
clrscr;
write('Nhap so n: ');readln(n);
k := length(n);s:=0;
for i:=1 to k do
begin
s := s + ord(n[i])-48;
end;
Writeln('Tong la:',s);
readln
end.
Nhận xét: Khi sử dụng xâu chương trình có vẻ đơn giản hơn.
Bài 2.2 Viết chương trình nhập vào từ bàn phím số nguyên n (0<=n<=1011), in
ra màn hình số có giá trị lớn nhất được ghép từ các chữ số của N?
Ví dụ: Nhập vào n = 231 in ra màn hình 321.
Dữ liệu vào: N (0<=n<=1011)
Dữ liệu ra: Giá trị lớn nhất đươc ghép bởi các chữ số của N.
uses crt;
var n:int64;i,j,m,k:byte;
a:array[1 20] of byte;
procedure td(var x,y:byte);
var tg:byte;
begin
tg := x; x:=y; y:=tg;
end;
begin
clrscr;
write('Nhap so n: ');readln(n);
i:=1;
while n<>0 do
begin
a[i]:=n mod 10; n:=n div 10; i:=i+1
end;
for j:=i-1 downto 2 do
for k:=j-1 downto 1 do
if a[j]<a[k] then td(a[j],a[k]);
for j := i-1 downto 1 do write(a[j]);
readln
end.
Nhận xét: Sau khi lưu các chữ số của N vào mảng A, ta sắp xếp chúng theo thứ
tự không giảm rồi in ra màn hình các phần tử sau khi đã sắp xếp.
Trang 4uses crt;
var n:string;i,j,m,k:byte;
procedure td(var x,y:char);
var tg:char;
begin
tg := x; x:=y; y:=tg;
end;
begin
clrscr;
write('Nhap so n: ');readln(n);
i := length(n);
for j:=i downto 2 do
for k:=j-1 downto 1 do
if n[j]>n[k] then td(n[j],n[k]);
write(n);
readln
end.
Bài 2.3 Viết chương trình nhập vào từ bàn phím số nguyên n (0<=n<=1011), in
ra màn hình các số xuất hiện nhiều nhất trong các chữ số của N?
Ví dụ: Khi nhập N=6677028 chương trình sẽ ra màn hính 6 7
Dữ liệu vào: 6677028
Dữ liệu ra: 6 7
uses crt;
var n:int64;i,j,k,d,mx:byte;
a,b:array[1 20] of byte;
begin
clrscr;
write('Nhap so n: ');readln(n);
i:=1;
while n<>0 do
begin
a[i]:=n mod 10; n:=n div 10; i:=i+1
end;
mx:=0;
for j:=i-1 downto 1 do
begin
d:=0;
for k:=j-1 downto 1 do
if a[j]=a[k] then
begin d := d+1; if mx < d then mx:=d; end;
b[j]:=d;
end;
for k := i-1 downto 1 do if b[k]= mx then Write(a[k],' ');
readln
end
Trang 5Bài 2.4 Gọi abcd là một số có 4 chữ số Hãy lập chương trình tìm tất cả các số có 4
chữ số thỏa mãn biểu thức: abcd=(ab + cd) 2
Ví dụ: Số 2025=(20 + 25)2
Thuật toán:
- Kiểm tra tất cả các số có bốn chữ số theo các cách sau;
- Tách lấy hai số đầu, hai số sau của số có bốn chữ số để kiểm tra
- Kiểm tra các trường hợp có thể của mỗi chữ số
Var haisodau, haisocuoi, i : integer;
Begin
Writeln( 'Cac so thoa man dieu kien gom co');
For i:=1000 to 9999 do
begin
haisodau := i div 100;
haisocuoi := i mod 100;
If i=sqr(haisodau + haisocuoi) then write(i,' ');
end;
Readln;
End
Bài 2.5 Viết chương trình cho nhập hai số tự nhiên N và k Hãy cho biết chữ số thứ k
tính từ trái sang phải trong số N là số mấy? nếu k lớn hơn độ dài của N hoặc k bằng 0 thì thông báo (-1) không tìm được
Ví dụ 1: Với N và k được nhập: N = 65932, k = 4
Kết quả tìm được là 3
Ví dụ 2: Với N và k được nhập: N = 65932, k = 10
Kết quả được in ra là -1 ( k lớn hơn độ dài số N)
uses crt;
var n:qword;i,j,k:byte;
a:array[1 20] of byte;
begin
clrscr;
write('Nhap so n,k: ');readln(n,k);
i:=1;
while n<>0 do
begin
a[i]:=n mod 10; n:=n div 10; i:=i+1
end;
if (i-1 < k) or (k=0) then write('-1') else write(a[i-k]);
readln
end
Bài 2.6 Một số được gọi là số bậc thang nếu biểu diễn thập phân của nó có
nhiều hơn một chữ số đồng thời theo chiều từ trái qua phải, chữ số đứng sau không nhỏ hơn chữ số đứng trước Viết chương trình in ra các số bậc thang trong đoạn [n1, n2] với n1, n2 được nhập từ bàn phím.
Var i,n1,n2: integer;
Function BT(n:integer):Boolean;
Var so:byte;
Begin
bt := true;
While n>=10 do
Begin
Trang 6so := n mod 10;
n := n div 10;
if so < (n mod 10) then exit(false);
End;
End;
Begin
Write('Nhap n1,n2: ');Readln(n1,n2);
For i := n1 to n2 do if BT(i) then Write(i,' ');
Readln
End
Bài 2.7 Năm 1973, nhà Toán học Neil Sloan đưa ra khái niệm độ bền của một
số nguyên không âm N như sau:
- Nếu N có một chữ số thì độ bền của N bằng 0
- Nếu N có từ 2 chữ số trở lên thì độ bền của N bằng độ bền của số nguyên là tích các chữ số của N cộng 1
Cho N, tìm số bé hơn N có độ bền lớn nhất (0 ≤ N ≤ 2.109).
Nhập N = 100
In ra màn hình 77
1+1+1+1 =0+1+1+1+1 = 4
Giải thuật:
- Để tìm độ bền một số cần một hàm tính tích các chữ số của n tich(n).
- Cho d = 0 Lặp lại điều kiện n >9 thì tăng d lên 1 thay n = tich(n).
uses crt;
Var n,d,i,j,max,k:longint;
Function tich(n:Longint):Longint;
Var t:integer;
Begin
if n=0 then t:=0 else t:=1;
While n <> 0 do
Begin
t := t*(n mod 10); n := n div 10;
End;
tich := t;
End;
Begin
Write('Nhap n: ');Readln(n);
max := 0;
For i:=1 to n do
Begin
d := 0;j := i;
While j>9 do
Begin
d := d+1; j := tich(j);
End;
if d>=max then begin max := d; k:= i end;
End;
write (k,' co do ben lon nhat = ',max);
Readln
End
Trang 7Bài 2.8 Viết chương trình nhập N từ bàn phím, in ra màn hình các số bé hơn N
có độ bền lớn nhất (0 ≤ N ≤ 2.109).
Ví dụ: Nhập vào N=200, in ra màn hình
77 co do ben max = 4
177 co do ben max = 4 uses crt;
Var n,d,i,j,max,k:longint;
a:array[1 1000000000] of byte;
Function tich(n:Longint):Longint;
Var t:integer;
Begin
if n=0 then t:=0 else t:=1;
While n <> 0 do
Begin
t := t*(n mod 10); n := n div 10;
End;
tich := t;
End;
Begin
Write('Nhap n: ');Readln(n);
max := 0;
For i:=n downto 1 do
Begin
d := 0;j := i;
While j>9 do
Begin
d := d+1; j := tich(j);
End;
if d>=max then begin max := d; a[i]:=max; end;
End;
for i := 1 to n do if a[i] = max then writeln(i,' co do ben max =
',a[i]);
Readln
End
Bài 2.9 Viết chương trình nhập N từ bàn phím, in ra màn hình số lượng các số
bé hơn N có độ bền lớn nhất (0 ≤ N ≤ 2.109).
Ví dụ: Nhập N=1000, kết quả in ra ‘Co 9 so co do ben max =5’;
uses crt;
Var n,d,i,j,max,k:longint;
Function tich(n:Longint):Longint;
Var t:integer;
Begin
if n=0 then t:=0 else t:=1;
While n <> 0 do
Begin
t := t*(n mod 10); n := n div 10;
End;
tich := t;
End;
Begin
Trang 8Write('Nhap n: ');Readln(n);
max := 0;
For i:=n downto 1 do
Begin
d := 0;j := i;
While j>9 do
Begin
d := d+1;
j := tich(j);
End;
if d>max then k:=0;
if d>=max then begin max := d; k:=k+1; end;
End;
writeln('Co ',k, ' so co do ben max = ',max);
Readln
End
Bài 3.10 Cho hai số nguyên dương x, y, ta xây dựng số z bằng cách ghép các
chữ số của x và y sao cho thứ tự các chữ số của x và y vẫn giữ nguyên trên z Tìm giá trị bé nhất và lớn nhất của z (1 <= x, y <= 108), dữ liệu đảm bảo không
có các chữ số 0 vô nghĩa của x và y.
Dữ liệu vào: 2 số nguyên dương x, y
Dữ liệu ra: Dòng thứ nhất ghi giá trị bé nhất của z và dòng thứ hai ghi giá trị lớn nhất của z
Giới hạn
Ví dụ: Nhập 13 26
In ra màn hình
1236 2613 var x,y:longint;
a,b:string;
function min(a,b:string):string;
begin
while (length(a)>0) and (length(b)>0) do
if a+b<b+a then begin min:=min+a[1];delete(a,1,1);end
else begin min:=min+b[1]; delete(b,1,1); end;
min:=min+a+b;
writeln(min);
end;
function max(a,b:string):string;
begin
max:='';
while (length(a)>0) and (length(b)>0) do
if a+b>b+a then begin max:=max+a[1];delete(a,1,1);end
else begin max:=max+b[1]; delete(b,1,1); end;
max:=max+a+b;
writeln(max);
end;
Trang 9read(x,y);str(x,a);str(y,b);
min(a,b);
max(a,b);
end.
III Số nguyên tố
Thuật toán kiểm tra nguyên tố theo phương pháp thô sơ tốt nhất, thực hiện theo cách sau:
Nếu n < 2 thì khẳng định n không là số nguyên tố.
Nếu n = 2 hoặc n = 3 thì khẳng định n là số nguyên tố ngược lại thì nếu n mod
2 =0 hoặc n mod 3 =0 thì n không là số nguyên tố.
Với các trường hợp khác ta sẽ thử các số có dạng 6k 1 nên ta gán i=5
Trong khi i*i <= n thì ta kiểm tra nếu n mod i = 0 hoặc n mod i+2 = 0 thì ta khẳng định n không là nguyên tố Tăng biến đếm i lên 6 và tiếp tục thực hiện
Bài 3.1 Nhập vào từ bàn phím số nguyên N (0<N<2.1011) Viết chương trình kiểm tra xem N có là số nguyên tố hay không?
Ví dụ: Nhập N=7, thông báo ra màn hình 7 la SNT
Nhập N=8, thông báo ra màn hình 8 khong la SNT.
uses crt;
var n,i:int64;
function nt(n:int64):boolean;
var i:int64;
begin
nt:=true;
if n<2 then exit(false);
if (n=3) or (n=2) then exit(true)
else if (n mod 2 =0) or (n mod 3 = 0) then exit(false);
i:=5;
while i*i<=n do
begin
if (n mod i = 0) or (n mod (i+2) = 0 ) then exit(false);
i:=i+6;
end;
end;
begin
write('Nhap n = '); readln(n);
if nt(n) then writeln(n,' la SNT') else writeln(n,' khong la SNT');
readln;
end
Bài 3.2 Viết chương trình đếm và in ra màn hình số lượng số nguyên tố nhỏ hơn
số nguyên N (0<N<1011)được nhập vào từ bàn phím.
Ví dụ: Nhập N=100, in ra màn hình 25
Nhập N=1000, in ra màn hinh 168
uses crt;
var n,i,d:int64;
function nt(n:int64):boolean;
var i:int64;
begin
Trang 10end;
begin
write('Nhap n = '); readln(n);
if n = 1 then d:=0 else d := 1;
i := 3;
while i<=n do
begin
if nt(i) then d:=d+1;
i := i+2;
end;
write(d);
readln;
end
Bài 3.3 Viết chương trình in ra màn hình các cách phân tích một số nguyên N
chẵn (3<n<1011) được nhập từ bàn phím, thành tổng của 2 số nguyên tố?
Ví dụ: Nhập n =8, in ra màn hình =3 + 5
Nhập n=12, in ra màn hinh =5 + 7
uses crt;
var n,i:int64;
function nt(n:int64):boolean;
var i:int64;
begin
…
end;
begin
write('Nhap n = '); readln(n);
i := 1;
while i<= n div 2 do
begin
if nt(i) and nt(n-i) then writeln('=',i,' + ',n-i);
i := i+1;
end;
readln;
end
Bài 3.4 Viết chương trình in ra màn hình các cách phân tích một số nguyên N lẻ
(5<n<1011) được nhập từ bàn phím, thành tổng của 3 số nguyên tố?
Ví dụ: Nhập n =7, in ra màn hình = 2+2+3;
Nhập n=11, in ra màn hình = 2+2+7; = 3+3+5;
uses crt;
var n,i,j:int64;
function nt(n:int64):boolean;
var i:int64;
begin
…
end;
begin
repeat
Trang 11write('Nhap n = '); readln(n);
until (n>5) and (n mod 2 = 1);
i := n-1;
while i >= n div 3 do
begin
j := 2;
while j <= n div 3 do
begin
if nt(i) and nt(j) and nt(n-i-j) and (j <= n-i-j) and ( n-i-j <= i)
then writeln('=',j,' + ',n-i-j,' + ',i,';');
j := j+1;
end;
i:=i-1
end;
readln;
end
Bài 3.5 Viết chương trình in ra màn hình số nguyên tố lớn nhất, nhỏ hơn số
nguyên N (3<n<1011) được nhập từ bàn phím và số nguyên tố nhỏ nhất, lớn hơn
N ?
Ví dụ: Nhập n =10, in ra màn hình 7 11;
Nhập n=1001, in ra màn hình 997 1009;
uses crt;
var n,i,j:int64;
function nt(n:int64):boolean;
var i:int64;
begin
…
end;
begin
repeat
write('Nhap n = '); readln(n);
until (n>3);
i := n-1;
while not(nt(i)) do i:=i-1;write(i,' ');
j := n+1;
while not(nt(j)) do j:=j+1;write(j);
readln;
end
Bài 3.6. Cho một số nguyên dương n nhập vào từ bàn phím (1<= n <= 600.000),
xác định xem số nguyên tố thứ n có giá trị là bao nhiêu?
Ví dụ: Nhập N= 10000, in ra màn hình 104729
Nhập N= 500000, in ra màn hình 7368787
const nm = 10000000;
var n,i,j,d:longint;
a,b:array[1 nm] of longint;
begin
readln(n);
a[1]:=1;
d:=0;
Trang 12for i:=2 to trunc(sqrt(nm)) do
if a[i]=0 then
for j := i to nm div i do a[i*j]:=1;
for i:=1 to nm do
if a[i]=0 then
begin
inc(d); b[d]:=i;
end;
write(b[n]);
readln;
end
Bài 3.7 Bạn hãy cho biết số lượng tối thiểu các số nguyên tố có một chữ số mà tổng của chúng bằng N Hay nói cách khác, hãy tìm cách phân tích N thành tổng của các số nguyên tố có một chữ số mà số lượng số hạng là nhỏ nhất Với số nguyên N được nhập vào từ bàn phím (N <= 106) In ra màn hình số lượng nhỏ nhất tìm được Nếu như không thể phân tích N thành tổng các số nguyên tố có 1 chữ số thì xuất ra -1.
Ví dụ: Nhập N= 21, in ra màn hình 3 (Vì 21 = 7+7+7)
Nhập N = 1000, in ra màn hình 144
Thuật toán: Để số lượng số hạng là nhỏ nhất, nếu n <=1 ta thông báo -1 ngược lại ta phân tích N thành tổng nhiểu nhất các số nguyên tố là 7 bằng cách dung phép chia nguyên cho 7.
Tiếp theo phần dư là 0 thì không phân tích nữa, nếu phần dư là 1 ta sẽ phải phân tích 8 thành tổng 2 số nguyên tố, nếu phần dư là 2 và 3, 5 ta có 2, 3, 5 là số nguyên tố Nếu phần dư là 4,6 ta sẽ phân tích thành 2 số nguyên tố.
var t,i:longint;
s:array[0 6] of byte=(0,1,1,1,2,1,2);
begin
readln(t);
if t<=1 then writeln(-1)
else
writeln(t div 7+s[t mod 7]);
readln;
end
Bài 3.8 Đếm xem có bao nhiêu số nguyên tố trong đoạn [L;R]
Dữ liệu nhập:
- Một dòng duy nhất gồm 2 số L,R ( 2≤ L < R ≤ 2.109,R-L ≤ 1000000)
Dữ liệu xuất:
- Ghi số lượng số nguyên tố trong đoạn [L;R]
Ví dụ: Nhập 2 10
In ra màn hình 4
var r,l,i,d:longint;
function nt(n:longint):boolean;
var i:longint;
begin
nt:=true;