Sáng kiến kinh nghiệm Hệ thống giải bài trực tuyến nhập môn lập trình với C++

Theo Chƣơng trình giáo dục phổ thông 2018 đƣợc Bộ Giáo dục và Đào

tạo ban hành kèm Thông tƣ số 32/2018/TT-BGDĐT ngày 26/12/2018, môn Tin

học có triết lý cốt lõi tạo ra một thế hệ mới có tƣ duy áp dụng công nghệ trong

giải quyết các vấn đề thực tế. Vì vậy, những kiến thức về phần giải thuật và lập

trình đóng vai trò rất quan trọng trong chƣơng trình tin học ở bậc THPT.

Hiện tại chất lƣợng việc dạy học Tin học ở nhà trƣờng THCS và THPT

trong cả nƣớc nói chung, tỉnh Nghệ An nói riêng còn ở mức độ khá thấp, tuy đã

đƣợc chú trọng, song trình độ giáo viên còn hạn chế, việc tìm tòi kiến thức còn

gặp nhiều khó khăn trong xu thế liên tục đổi mới công nghệ nói chung và bộ

môn Tin học nói riêng. Lập trình là một phần rất quan trọng trong nội dung

chƣơng trình bộ môn Tin học hiện tại và cả nội dung chƣơng trình Giáo dục phổ

thông 2018, là mạch kiến thức quan trọng nhất trong 3 mạch kiến thức của Tin

học bao gồm: CS, ICT, DL.

Hiện tại phần lập trình trong SGK Tin học cơ bản đang minh họa bằng

ngôn ngữ lập trình Pascal. Đây là ngôn ngữ có nhiều đóng góp trong lịch sử phát

triển của Tin học thế giới. Tuy nhiên, với xu thế phát triển của thời đại 4.0, ngôn

ngữ Pascal không còn đƣợc hỗ trợ nhiều và chính thức bị Tổ chức Olympic Tin

học Quốc tế đƣa ra ngoài danh sách ngôn ngữ lập trình trong nhà trƣờng phổ

thông từ năm 2020.

pdf146 trang | Chia sẻ: lacduong21 | Lượt xem: 1686 | Lượt tải: 1Download
Bạn đang xem 20 trang mẫu của tài liệu "Sáng kiến kinh nghiệm Hệ thống giải bài trực tuyến nhập môn lập trình với C++", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
ơng . Hãy tính 
1 2
...
n
S
n n n
     
        
     
. 
Nhận xét thấy: có nhiều đoạn mà 
1
...
i i j
n n n
     
       
     
. Vì vậy ta sẽ tìm các 
đoạn nhƣ vậy và nhân với độ dài của đoạn với độ lớn của 
i
n
 
 
 
. 
#include 
using namespace std; 
long long n,s=0,i=1; 
int main() 
{ 
 cin>>n; 
 while(i<=n) 
 { 
 long long t=n/i; 
 s+=(n/t-i+1)*t; 
Algorithm with C++ 
126 
 i=n/t+1; 
 } 
 cout<<s; 
} 
Algorithm with C++ 
127 
CHƢƠNG 11 – ĐỆ QUY 
A. KIẾN THỨC GHI NHỚ 
1. Khái niệm đệ quy 
Chƣơng trình con đệ quy là các chƣơng trình con có lời gọi nó trong chính 
chƣơng trình của nó. Điều này có thể hơi khác lạ với phƣơng thức lập trình logic 
tuần tự nhƣng đây lại là một điểm mạnh của các ngôn ngữ lập trình với việc 
quản lý ngăn xếp chƣơng trình con để cất ngữ cảnh hiện tại và tiếp tục giải bài 
toán ở mức nhỏ hơn cho đến khi gặp trƣờng hợp nhỏ nhất. Chƣơng trình con đệ 
quy có ƣu thế khi giải quyết các bài toán có dạng công thức truy hồi, các bài 
toán về chia để trị, các bài toán quay lui vét cạn. Một chƣơng trình đệ quy 
thƣờng có cấu trúc nhƣ sau: 
 (danh sách tham số) 
{ 
 if(trường hợp dừng đệ quy) 
 return ; 
 else 
 return (tham số cấp nhỏ hơn); 
} 
Ta chú ý rằng chƣơng trình con đệ quy phải có hai phần rõ rệt. Một là phần 
trƣờng hợp dừng – trƣờng hợp nhỏ nhất của bài toán, không có phần trƣờng hợp 
dừng này hoàn toàn chƣơng trình sẽ lặp tới mức tràn ngăn xếp chƣơng trình con. 
Hai là trƣờng hợp gọi đệ quy, trƣờng hợp này sẽ đƣa bài toán đang giải về bài 
toán cùng dạng với cấp độ nhỏ hơn. Khi có lời gọi đệ quy, trình biên dịch sẽ liên 
tục cất ngữ cảnh vào bộ nhớ ngăn xếp chƣơng trình con cho tới trƣờng hợp dừng 
sẽ lại quay trở lại lấy giá trị các biến trong ngăn xếp chƣơng trình con để tính 
ngƣợc lên lời gọi đầu tiên. Vì vậy khi gọi đệ quy chúng ta lƣu ý không để lời gọi 
quá sâu để dẫn tới việc tràn bộ nhớ ngăn xếp chƣơng trình con. 
2. Ví dụ minh họa 
Ta xét một ví dụ mở đầu về đệ quy nhƣ sau: Tính 
#include 
using namespace std; 
long long gt(long long n){ 
 if(n==0) return 1;// Trường hợp dừng 
 else return n*gt(n-1);//Lời gọi đệ quy cấp thấp hơn 
} 
int main() 
Algorithm with C++ 
128 
{ 
 long long n; 
 cin>>n; 
 cout<<gt(n); 
} 
Với chƣơng trình trên khi nhập bằng ta có một sơ đồ đệ quy nhƣ sau: 
Chú ý rằng trong chƣơng trình con đệ quy dứt khoát phải có trƣờng hợp dừng, 
khi đó mới thoát ra khỏi vòng lặp đệ quy. Câu lệnh đệ quy thƣờng ngắn gọn, súc 
tích, gần với bản chất toán học của bài toán. Tuy nhiên việc gọi đệ quy quá sâu 
sẽ phải cất ngữ cảnh quá nhiều dẫn tới tràn ngăn xếp chƣơng trình con. Mỗi 
trình biên dịch ngôn ngữ thƣờng đƣợc cấp một dung lƣợng nhất định cho ngăn 
xếp chƣơng trình con, ta cũng có thể mở rộng trong phạm vi cho phép, tuy nhiên 
nó sẽ phụ thuộc nhiều vào bộ nhớ trên máy tính. Thực tế, với việc tính !n theo 
cách viết đệ quy không đem lại ƣu thế. Vì vậy đây chỉ là một ví dụ mô tả cho đệ 
quy mà thôi, chúng ta ít sử dụng nó trực tiếp trong tính toán nhƣ trên. 
3. Một số ứng dụng của đệ quy 
Đệ quy có nhiều ứng dụng trong lập trình. Một trong những ứng dụng thƣờng 
gặp là chia để trị và liệt kê tổ hợp. Cấu trúc của các giải thuật chia để trị đƣa 
việc giải quyết bài toán về giải nhiều bài toán cùng dạng nhƣng có cấp thấp hơn 
theo mô hình cây và sử dụng đƣợc lời giải ở cấp thấp hơn để độ phức tạp bài 
toán giảm xuống: 
Điển hình cho dạng toán này đƣợc mô tả trong Ví dụ 11.1 
Bài toán 
cấp n 
Bài toán 
cấp n-1 
Bài toán 
cấp n-2 
Bài toán 
cấp n-2 
Bài toán 
cấp n-1 
Bài toán 
cấp n-2 
Algorithm with C++ 
129 
Ngoài ra để liệt kê các cấu hình tổ hợp thì cấu trúc đệ quy quay lui rất thuận tiện 
cho việc liệt kê này. 
Ta có mô hình liệt kê tổ hợp nhƣ sau: 
void Try (int i)//Xây dựng thành phần thứ i 
{ 
 ; 
 for(xi thuộc Si) 
 { 
 if (tìm thấy nghiệm) ; 
 else Try(i+1); 
 ; 
 } 
} 
Trong đó Si là tập hợp các giá trị mà xi có thể nhận đƣợc với xi là thành phần 
thứ i của cấu hình ta cần xây dựng. 
Ta xem xét ví dụ minh họa cho dạng toán này trong Ví dụ 11.2 
B. CÁC VÍ DỤ MẪU 
Ví dụ 11.1: Xét chƣơng trình tính bằng chia để trị với độ phức 
tạp . 
#include 
#define mod 1000000007 
#define ll long long 
using namespace std; 
ll mu(ll a, ll n) // tính a^n%mod bằng đệ quy chia để trị 
{ 
 if(n==0) return 1; 
 ll tam = mu(a,n/2); 
 tam = (tam*tam)%mod; 
 if(n%2==1) tam = (tam*a)%mod; 
 return tam; 
} 
int main() 
{ 
 long long a,n; 
 cin>>a>>n; 
 cout<<mu(a,n); // độ phức tạp thuật toán là O(logn) 
} 
Chú ý rằng nếu chúng ta sử dụng vòng lặp for để tính na thì độ phức tạp của giải 
thuật sẽ là – chỉ có thể giải đƣợc cho n cỡ 6 810 10  trong thời gian giây. 
Algorithm with C++ 
130 
Ví dụ 11.2: Ta xét ví dụ liệt kê dãy nhị phân có độ dài n nhƣ sau: 
#include 
#define ll long long 
using namespace std; 
int x[30],n; 
void Xuat() 
{ 
 for(int k=1;k<=n;k++) cout<<x[k]; 
 cout<<endl; 
} 
void Try(ll i) 
{ 
 for(int j=0;j<=1;j++) 
 { 
 x[i]=j; 
 if(i==n) Xuat(); 
 else Try(i+1); 
 } 
} 
int main() 
{ 
 cin>>n; 
 Try(1); 
} 
Lời gọi đệ quy vét cạn thƣờng bắt đầu với nghĩa là xây dựng thành phần 
thứ nhất của i. 
Ví dụ 11.3: Chƣơng trình sau sẽ liệt kê ra các hoán vị của tập  1,2,...,X n . 
Ta biết khi xây dựng hoán vị thì các thành phần xây dựng không đƣợc phép lặp 
lại. Vì vậy ta phải sử dụng một mảng đánh dấu d[] để đánh dấu cho các giá trị 
đã đƣợc chọn để không chọn lại. Đoạn chƣơng trình liệt kê hoán vị nhƣ sau: 
Algorithm with C++ 
131 
#include 
#define ll long long 
#define fo(i,a,b) for(int i=a;i<=b;i++) 
using namespace std; 
ll n,x[30],d[30]; 
void Xuat() 
{ 
 fo(k,1,n) cout<<x[k]; 
 cout<<'\n'; 
} 
ll Try(ll i) 
{ 
 fo(j,1,n) 
 if(d[j]==0)// nếu j chưa được chọn 
 { 
 x[i]=j;//chọn x[i] là j 
 d[j]=1;//đánh dấu j đã được chọn 
 if(i==n) Xuat();// in ra khi chọn tới xn 
 else Try(i+1); // chưa chọn đến xn thì chọn tiếp 
 d[j]=0;// quay lại bỏ đánh dấu để chọn tiếp sau 
 } 
} 
int main() 
{ 
 cin>>n; 
 Try(1); 
} 
Bên cạnh phƣơng pháp này kể từ phiên bản C14, ta có hàm 
next_permutation() để sinh hoán vị kế tiếp, đây là một cách code khá gọn 
gàng nhƣ sau: 
#include 
using namespace std; 
long long n,a[30]; 
int main() 
{ 
 cin>>n; 
 for(int i=1;i<=n;i++) a[i]=i; 
 do 
 { 
 for(int i=1;i<=n;i++) cout<<a[i]; 
 cout<<'\n'; 
Algorithm with C++ 
132 
 } 
 while(next_permutation(a+1,a+n+1)); 
} 
C. BÀI TẬP ÁP DỤNG 
Bài 11.1 – (N1101A) Số tập con 
Yêu cầu: Hãy đếm số tập hợp con của tập  1,2,...X n . 
Dữ liệu: Một dòng ghi số nguyên không âm 
9(0 10 )n n  . 
Kết quả: In ra số các tập con của tập X . Kết quả có thể rất lớn nên ta sẽ chia 
lấy dƣ cho 910 7 khi in ra. 
Ví dụ: 
input output 
3 8 
Bài 11.2 – (N1102A) Liệt kê nhị phân 
Yêu cầu: Hãy in ra các dãy nhị phân độ dài n 
Input: Một dòng ghi số nguyên (0 20)n n  
Output: In ra các dãy nhị phân theo thứ tự từ điển. 
Ví dụ: 
input output 
2 00 
01 
10 
11 
Bài 11.3 – (N1103A) Liệt kê tam phân 
Yêu cầu: Dãy tam phân là dãy chỉ gồm các ký tự 0, 1, 2 dùng để biển diễn các 
số trong hệ cơ số 3. Ví dụ ta có các dãy tam phân độ dài 2 là: 00, 01, 02, 10, 11, 
12, 20, 21, 22. Hãy liệt kê theo thứ tự từ điển các dãy tam phân độ dài n . 
Dữ liệu: Một dòng ghi số nguyên không âm (0 10)n n  . 
Kết quả: In ra các dãy tam phân theo thứ tự từ điển. 
Ví dụ: 
input output 
2 00 
01 
02 
10 
11 
Algorithm with C++ 
133 
12 
20 
21 
22 
Bài 11.4 – (N1104B) Liệt kê chỉnh hợp 
Yêu cầu: Trong toán học, chỉnh hợp là cách chọn những phần tử từ một nhóm 
lớn hơn và có phân biệt thứ tự, trái với tổ hợp là không phân biệt thứ tự. 
Theo định nghĩa, chỉnh hợp chập k của n phần tử là bộ sắp thứ tự gồm k phần 
tử của tập hợp gồm n phần tử. Hãy liệt kê các chỉnh hợp chập k của n phần tử 
của  1,2,...,X n 
Dữ liệu nhập: Một dòng một gồm  , 1 8k n k n   . 
Kết quả: Mỗi dòng in một chỉnh hợp chập k của n , các chỉnh hợp in theo thứ 
tự từ điển. 
Ví dụ: 
input output 
2 3 
1 2 
1 3 
2 1 
2 3 
3 1 
3 2 
Bài 11.5 – (N1105C) Liệt kê chỉnh hợp tập A 
Yêu cầu: Trong bài tập này bạn đƣợc cho một tập hợp A gồm n phần tử số 
nguyên khác nhau. Bạn hãy liệt kê các chỉnh hợp không lặp chập k của n phần 
tử này. 
Dữ liệu nhập: 
- Dòng một gồm  , 1 8k n k n   . 
- Dòng hai là n phần tử của tập A. 
Kết quả: 
- Mỗi dòng in một chỉnh hợp chập k của n , các chỉnh hợp in theo thứ tự từ 
điển. 
- Dòng cuối cùng in số lƣợng chỉnh hợp liệt kê đƣợc. 
Ví dụ: 
input output 
2 3 
1 9 4 
1 4 
1 9 
Algorithm with C++ 
134 
4 1 
4 9 
9 1 
9 4 
6 
Bài 11.6 – (N1106B) Liệt kê tổ hợp 
Yêu cầu: Trong toán học, tổ hợp chập k của n là cách chọn tập con gồm k 
phần tử trong tập có n phần tử. Ở đây, bạn đƣợc yêu cầu in ra tất cả các tổ hợp 
chập k của tập  1,2,...,X n . 
Dữ liệu: Một dòng một gồm  , 1 8k n k n   . 
Kết quả: 
- Mỗi dòng in một tổ hợp chập k của theo thứ tự từ điển. 
- Dòng cuối cùng in số lƣợng tổ hợp liệt kê đƣợc. 
Ví dụ: 
input output 
2 3 1 2 
1 3 
2 3 
3 
Bài 11.7 – (N1107C) Liệt kê tổ hợp tập A 
Yêu cầu: Hãy in ra các tổ hợp chập k của tập số nguyên A gồm n phần tử. 
Dữ liệu: 
- Dòng đầu tiên một gồm hai số nguyên  , 1 8k n k n   . 
- Dòng tiếp theo gồm n số nguyên trong tập A. 
Kết quả: 
- Mỗi dòng in một tổ hợp chập k của theo thứ tự từ điển. 
- Dòng cuối cùng in số lƣợng tổ hợp liệt kê đƣợc. 
Ví dụ: 
input output 
2 3 
1 9 4 
1 4 
1 9 
4 9 
3 
Algorithm with C++ 
135 
Bài 11.8 – (N1108B) Liệt kê xâu ký tự AB 
Yêu cầu: Hãy liệt kê các xâu độ dài n chỉ gồm hai kí tự ′A′ hoặc ′B′ mà không 
có hai kí tự ′B′ nào đứng cạnh nhau. 
Dữ liệu: Một dòng ghi số nguyên  20n n  . 
Kết quả: In ra các xâu ký tự theo thứ tự từ điển. 
Ví dụ: 
input output 
3 AAA 
AAB 
ABA 
BAA 
BAB 
Bài 11.9 – (N1109D) Liệt kê xâu hợp lệ 
Yêu cầu: Hãy liệt kê các cách đặt n dấu mở ngoặc và n dấu đóng ngoặc sao 
cho biểu thức đó hợp lệ. 
Dữ liệu: Một dòng ghi số nguyên  20n n  . 
Kết quả: In ra các xâu ký tự theo thứ tự từ điển. 
Ví dụ: 
input output 
3 AAA 
AAB 
ABA 
BAA 
BAB 
Bài 11.10 – (N1110E) Liệt kê xâu con 
Yêu cầu: Hãy liệt kê tất cả các xâu con khác nhau của xâu S. 
Dữ liệu: Một dòng ghi xâu S  . 15S length  gồm các ký tự từ a đến z. 
Kết quả: In ra các xâu con khác nhau của S theo thứ tự từ điển. 
Ví dụ: 
input output 
abc a 
ab 
abc 
ac 
b 
bc 
c 
Algorithm with C++ 
136 
Bài 11.11– (N1111D) Số mũ 1 
Yêu cầu: Cho hai số nguyên a, n. Tính  9% 10 7na  . 
Dữ liệu: Một dòng ghi hai số nguyên  9, 0 , 10a n a n  . 
Kết quả: In ra kết quả là tổng  9% 10 7na  . 
Ví dụ: 
input output 
2 3 8 
Bài 11.12 – (N1112E) Số mũ 2 
Yêu cầu: Cho số nguyên n, K tính  0 1 11.2 2.2 ... .2 %nS n K    . 
Dữ liệu: Một dòng ghi hai số nguyên  9n,K 0 , K 10n  . 
Kết quả: In ra kết quả là tổng S . 
Ví dụ: 
input output 
1 10 1 
Bài 11.13 – (N1113E) Số mũ 3 
Yêu cầu: Cho số nguyên n, tính 1 21 ... nS a a a     . Kết quả có thể rất lớn 
nên chia lấy dƣ cho 910 7 khi in ra. 
Dữ liệu: Một dòng ghi hai số nguyên  9, 0 , 10a n a n  . 
Kết quả: In ra kết quả là tổng  9% 10 7S  . 
Ví dụ: 
input output 
2 9 1023 
Bài 11.14 – (N1114E) Quân hậu 
Yêu cầu: Cho bàn cờ vua có kích cỡ . Hãy tìm cách xếp quân hậu trên 
bàn cờ sao cho các quân hậu không ăn đƣợc nhau. 
Dữ liệu: Một dòng ghi một số nguyên dƣơng 
Kết quả: In ra kết quả là số cách sắp xếp quân hậu trên bàn cờ. 
Ví dụ: 
input output 
8 92 
Algorithm with C++ 
137 
D. HƢỚNG DẪN GIẢI MỘT SỐ BÀI TẬP 
Bài 11.4 – (N1104B) Liệt kê chỉnh hợp 
#include 
#define ll long long 
#define fo(i,a,b) for(int i=a;i<=b;i++) 
#define nmax 10000005 
using namespace std; 
ll n,k,a[30],b[30],dem=0; 
ll qlui(ll x) 
{ 
 fo(i,1,n) if(N[i]==0) 
 { 
 a[x]=i; 
 b[i]=1;// Đánh dấu i đã được chọn 
 if(x==k) 
 { 
 fo(j,1,k) cout<<t[a[j]]<<' '; 
 cout<<'\n'; 
 } 
 else qlui(x+1); 
 b[i]=0;// Bỏ đánh dấu để quay lui chọn lại 
 } 
} 
int main() 
{ 
 cin>>k>>n; 
 fo(i,1,n) cin>>t[i]; 
 sort(t+1,t+1+n); 
 qlui(1); 
 cout<<dem; 
} 
Bài 11.5 – (N1105B) Liệt kê chỉnh hợp tập A 
#include 
#define ll long long 
#define fo(i,a,b) for(int i=a;i<=b;i++) 
#define nmax 10000005 
using namespace std; 
ll n,k,a[30],b[30],t[30],dem=0; 
ll Try(ll x) 
{ 
Algorithm with C++ 
138 
 fo(i,1,n) if(N[i]==0) 
 { 
 a[x]=i; 
 b[i]=1; 
 if(x==k) 
 { 
 fo(j,1,k) cout<<t[a[j]]<<' '; 
 cout<<'\n'; 
 dem++; 
 } 
 else Try(x+1); 
 b[i]=0; 
 } 
} 
int main() 
{ 
 cin>>k>>n; 
 fo(i,1,n) cin>>t[i]; 
 sort(t+1,t+1+n); 
 Try (1); 
 cout<<dem; 
} 
Bài 11.6 – (N1105B) Liệt kê tổ hợp 
Yêu cầu: Trong toán học, tổ hợp chập k của n là cách chọn tập con gồm k 
phần tử trong tập có n phần tử. Ở đây, bạn đƣợc yêu cầu in ra tất cả các tổ hợp 
chập k của tập  1,2,...,X n . 
#include 
#define fo(i,a,b) for(int i=a;i<=b;i++) 
using namespace std; 
long long n,k,a[20],t=1,m=1; 
void Try(int i) 
{ 
 fo(j,a[i-1]+1,n-k+i) 
 { 
 a[i]=j; 
 if(i==k) 
 { 
 fo(N,1,i) cout<<a[b]<<' '; 
 cout<<'\n'; 
 } 
Algorithm with C++ 
139 
 else Try(i+1); 
 } 
} 
int main() 
{ 
 cin>>n>>k; 
 fo(i,1,n) 
 { 
 t*=i; 
 if(i<=min((n-k),k)) m=m*i*i; 
 else if(i<=max((n-k),k)) m*=i; 
 } 
 cout<<t/m<<'\n'; 
 a[0]=0; 
 Try(1); 
} 
Bài 11.8 – (N1108C) Liệt kê xâu ký tự AB 
Yêu cầu: Hãy liệt kê các xâu độ dài n chỉ gồm hai kí tự ′A′ hoặc ′B′ mà không 
có hai kí tự ′B′ nào đứng cạnh nhau. 
#include 
using namespace std; 
#define ll long long 
ll n,k,x[25]; 
bool check(ll x[]){ 
 for(int i = 1;i<=k;i++){ 
 if(x[i]=='B'and x[i+1]=='B'){ 
 return false; 
 } 
 } 
 return true; 
} 
void Xuat(ll x[]) 
{ 
 for(int i = 1;i<=k;i++){ 
 cout<<char(x[i]); 
 } 
 cout<<endl; 
} 
void Try(ll i){ 
 for(int j = 'A';j<='B';j++){ 
Algorithm with C++ 
140 
 x[i]=j; 
 if(i==k){ 
 if(check(x)) Xuat(x); 
 } 
 else Try(i+1); 
 } 
} 
int main() 
{ 
 cin>>k; 
 Try(1); 
} 
Bài 11.9 – (N1109D) Liệt kê xâu hợp lệ 
Yêu cầu: Hãy liệt kê các cách đặt n dấu mở ngoặc và n dấu đóng ngoặc sao 
cho biểu thức đó hợp lệ. 
#include 
using namespace std; 
#define ll long long 
ll n,k,x[25]; 
bool check(ll x[]){ 
 for(int i = 1;i<=k;i++){ 
 if(x[i]=='B'and x[i+1]=='B') return false; 
 } 
 return true; 
} 
void Xuat(ll x[]) 
{ 
 for(int i = 1;i<=k;i++){ 
 cout<<char(x[i]); 
 } 
 cout<<endl; 
} 
void Try(ll i){ 
 for(int j = 'A';j<='B';j++){ 
 x[i]=j; 
 if(i==k){ 
 if(check(x)) Xuat(x); 
 } 
 else Try(i+1); 
 } 
Algorithm with C++ 
141 
} 
int main() 
{ 
 cin>>k; 
 Try(1); 
} 
Bài 11.10 – (N1110E) Liệt kê xâu con 
Yêu cầu: Hãy liệt kê các cách đặt n dấu mở ngoặc và n dấu đóng ngoặc sao 
cho biểu thức đó hợp lệ. 
#include 
using namespace std; 
string s, t; 
int n; 
set res; 
void Try(int x) 
{ 
 if(x > n) 
 { 
 if(t.size() != 0) res.insert(t); 
 return; 
 } 
 for(int i = 0; i <= 1; i++) 
 { 
 if(i) t += s[x]; 
 Try(x + 1); 
 if(i) t.erase(t.size() - 1, 1); 
 } 
} 
int main() 
{ 
 cin >> s; 
 n = s.size() - 1; 
 Try(0); 
 for(auto s : res) cout << s << '\n'; 
} 
Bài 11.11 – (N1111D) Số mũ 1 
#include 
#define ll long long 
#define mod 1000000007 
Algorithm with C++ 
142 
using namespace std; 
ll power(ll a, ll n) 
{ 
 if(n == 0) return 1; 
 ll tam = power(a,n/2); 
 tam= (tam*tam)%mod; 
 if(n % 2 == 1) 
 tam=(tam*a)%mod; 
 return tam; 
} 
int main() 
{ 
 ll a,n; 
 cin>>a>>n; 
 cout<<power(a,n); 
} 
Bài 11.12 – (N1112E) Số mũ 2 
Yêu cầu: Cho số nguyên n, K tính  0 1 11.2 2.2 ... .2 %nS n K    . 
Trong bài này, ta sử dụng hàm tính nhanh mũ và phép nhân chia lấy dƣ chống 
tràn nhƣ sau: 
#include 
using namespace std; 
//Nhân chống tràn 
long long nhan(long long a,long long b,long long mod) 
{ 
 a%=mod; 
 b%=mod; 
 lo q=(long double) a*b/mod; 
 return ((a*b-q*mod)%mod+mod)%mod; 
}// Đây là một trick khá hay trong C++ 
long long mu(long long x,long long y,long long z) 
{ 
 if(y==0) return 1; 
 if(y==1) return x%z; 
 long long r=mu(x,y/2,z); 
 r=nhan(r,r,z); 
 if(y%2==1) r=nhan(r,x,z); 
 return r; 
} 
int main() 
Algorithm with C++ 
143 
{ 
 long long n,k; 
 while(cin>>n>>k) 
 cout<<nhan(mu(2,n,k),(n-1),k)+1<<'\n'; 
} 
Bài 11.13 – (N1113E) Số mũ 3 
Yêu cầu: Cho số nguyên , tính 1 21 ... nS a a a     . Kết quả có thể rất lớn 
nên chia lấy dƣ cho 910 7 khi in ra. 
Ta có 
1
1 2 11 ...
1
n
n aS a a a
a
 
     

. Từ đó ta sử dụng phép mũ chia để trị và 
định lý Fermat nhỏ để chia lấy dƣ cho một số nguyên tố để có đƣợc kết quả. 
Nội dung định lý Fermat nhỏ nhƣ sau: “Với p là số nguyên tố và 2a  thì 
 1 1 modpa p  ”. Từ đó suy ra đẳng thức     2% % % %pa p a p b p p
b
  . 
#include 
using namespace std; 
const int mod=1e9+7; 
long long mu(long long a, long long b) 
{ 
 if (N==0) return 1; 
 long long tmp=mu(a,b/2); 
 tmp=(tmp*tmp)%mod; 
 if (N%2==1) tmp=(tmp*a)%mod; 
 return tmp; 
} 
long long a,n; 
int main() 
{ 
 cin>>a>>n; 
 if (a==1) {cout<<n+1<<'\n';return 0;} 
 cout<<((mu(a,n+1)-1)*mu(a-1,mod-2))%mod;//Fermat nhỏ 
} 
Bài 11.14 – (N1114E) Quân hậu 
Yêu cầu: Cho bàn cờ vua có kích cỡ . Hãy tìm cách xếp quân hậu trên 
bàn cờ sao cho các quân hậu không ăn đƣợc nhau. 
Ở đây ta sử dụng kỹ thuật đệ quy quay lui và đánh dấu các hàng, cột, chéo 
chính, chéo phụ. 
Algorithm with C++ 
144 
#include 
#define fo(i,a,b) for(int i=a;i<=b;i++) 
#define ll long long 
using namespace std; 
ll n,q[20],s=1,t,dem=0; 
bool ok; 
void Try(ll r) //Quay lui vét cạn 
{ 
 fo(j,1,n) 
 { 
 ok=true; 
 fo(i,1,r-1) //Đánh dấu hàng, cột, chéo chính phụ 
 if(q[i]==j||q[i]==j+r-i||q[i]==j-r+i) ok=false; 
 if(ok) 
 { 
 q[r]=j; 
 if(r==n) dem++; 
 else Try(r+1); 
 } 
 } 
} 
int main() 
{ 
 cin>>n; 
 Try(1); 
 cout<<dem; 
} 
Algorithm with C++ 
145 
KẾT LUẬN 
Đề tài đã tạo đƣợc một hệ thống các ví dụ, bài tập nhập môn lập trình 
thuật toán với ngôn ngữ C++ phong phú đa dạng, phân hóa mức độ từ thấp đến 
cao theo thang đo Bloom (2001); hệ thống ví dụ và bài tập này sẽ góp phần giúp 
giáo viên, học sinh sử dụng trong thực tế học tập và giảng dạy lập trình thuật 
toán một cách dễ dàng hơn. 
Đề tài đã cài đặt thành công website JUDGE có tên  
- một dạng elearning trong giảng dạy lập trình là một công cụ rất hữu hiệu đang 
đƣợc nhiều quốc gia phát triển trên thế giới áp dụng. 
Đề tài góp phần tạo ra một sân chơi học tập và giảng dạy cho môn Tin học 
lập trình trong xu thế của thời đại 4.0. 
Hƣớng phát triển kế tiếp của đề tài là trên cơ sở cài đặt công cụ 
 - trang web có khả năng biên dịch, thông dịch các 
mã nguồn của nhiều loại ngôn ngữ; chúng tôi sẽ biên tập tiếp tục cuốn tài liệu 
nhập môn với Python và cuốn tài liệu nâng cao lập trình thuật toán với C++, 
đồng thời hoàn thiện các tính năng nâng cao khác cho website 
Algorithm with C++ 
146 
TÀI LIỆU THAM KHẢO 
1. Bộ Giáo dục và Đào tạo, Chƣơng trình giáo dục phổ thông môn Tin học 2018. 
Thông tƣ số 32/2018/TT-BGDĐT, Hà Nội. 
2. Hồ Sỹ Đàm, Sách giáo khoa Tin học 10 (2011). Nhà xuất bản giáo dục, Hà 
Nội. 
3. Hồ Sỹ Đàm, Sách giáo khoa Tin học 11 (2011). Nhà xuất bản giáo dục, Hà 
Nội. 
4. Hồ Sỹ Đàm, Sách bài tập Tin học 11 (2011). Nhà xuất bản giáo dục, Hà Nội. 
5. Stephen Prata, C Prime Plus (2014). Adison Wesley, NewYork. 
6. Thomas H. Cormen, Introduce to Algorithm (2001). The MIT Press. 

File đính kèm:

  • pdf7_SKKN_Tin_hoc_chuan_21-4-2020_7918abe938.pdf
Sáng Kiến Liên Quan