Lí do thay đổi: + Với mảng, khi tạo chỉ số, với kích thước mảng bằng 2 , phép nhân có thể được chuyển thành phép dịch bit, do đó sẽ tối ưu về tốc độ truy cập các phần tử mảng.. + Biến
Trang 1GIẢI ĐỀ KTLT K52 - ĐỀ 1 Câu 2 (0.75đ): Khi thay đổi khai báo:
char MaTran [80][30]
thành char MaTran [80][32]
Ý nghĩa: thay đổi chỉ số cột từ 30 lên 32 để làm tăng tốc độ tính toán địa chỉ mảng Lí do thay đổi:
+ Với mảng, khi tạo chỉ số, với kích thước mảng bằng 2 , phép nhân có thể được
chuyển thành phép dịch bit, do đó sẽ tối ưu về tốc độ truy cập các phần tử mảng
+ Ở đây, ta nhận thấy 30 ~32 = 2 Do đó khi truy cập phần tử MaTran [i, j] thì trình biên dịch
sẽ thay phép toán i*32+j bằng phép toán (i << 5) + j, nhanh hơn
Câu 4 (0.75đ): Tính giá trị mảng A sau khi thực hiện đoạn lệnh:
int A[]={6,13,34,19}
int *p=A; //p=A[0]
*p++; //p=A[1] -> A[]={6,13,34,19}
*p+=2; //A[1]+=2 -> A[]={6,15,34,19}
p+=2; //p=A[3] -> A[]={6,15,34,19}
*p+=2; //A[3]+=2 -> A[]={6,15,34,21}
Vậy mảng A sau khi thực hiện đoạn mã lệnh là: A[] = {6,15,34,21}
Câu 5 (1.0đ): Tinh chỉnh đoạn mã lệnh sau và giải thích lí do:
for (int i = 0 ; i < n; i++) {
if ( x == y*8 ) {
DoOneThing(i);
}
else if ( x == y/4 + z/4 ) {
DoSomeThingElse(i);
}
else {
DoAnotherThing(i);
}
}
+ Các cấu trúc rẽ nhánh if-else không phụ thuộc vòng lặp for, do đó ta đưa ra ngoài vòng lặp + Biến đổi các biểu thức nhân chia thành phép toán dịch bit để tăng tốc độ
Đoạn lệnh sau khi tinh chỉnh:
int i;
if (x == y<<3) {
for(i=0; i<n; i++)
DoOneThing(i);
}
else if (x == y>>2 + z>>2) {
for(i=0; i<n; i++)
Trang 2DoSomeThingElse(i);
}
else {
for(i=0; i<n; i++)
DoAnotherThing(i);
}
Câu 6 (0.75đ): Cải tiến đoạn mã lệnh sau:
for(int i=0;i<10;i++){
printf(“%f\n”,i*5*sin(a)); //a là hằng số
}
+ Đưa biểu thức bất biến sin(a) ra khỏi vòng lặp for
+ Mỗi vòng lặp ta nhân với 5 lần i, do đó thay đổi vòng lặp mỗi lần i tăng 5 đơn
vị
Đoạn mã sau khi cải tiến:
float M=sin(a);
for(int i=0;i<50;i+=5){
printf(“%f\n”,i*M);
}
Câu 9 (2đ): Xây dựng hàm sort danh sách LKĐ theo thứ tự tăng dần của info:
void sortAscending(node *head){
int temp;
for(node *p=head; p!=NULL; p=p->next)
for(node *q=p->next; q!=NULL; q=q->next)
if (p->data > q->data) {
temp = p->data;
p->data = q->data;
q->data = temp;
}
cout<<endl<<"Day sau khi sap xep tang la: ";
for(node *p=head; p!=NULL; p=p->next)
cout<<endl<<p->data;
}
Trang 3GIẢI ĐỀ KTLT K52 - ĐỀ 2 Câu 2 (1.0đ): Khi x có bit 1 ở vị trí lẻ (chẳng hạn x = 00 00 00 10) Ta có:
x & 2 = 00 00 00 10
x & 1 = 00 00 00 00
(x & 1) ^ (x & 2) = 00 00 00 10 (= 2)
==> b = 2 (sai, đáng lẽ b = 1)
Sửa lại: thay x&2 bằng (x&2)>>1
Đoạn mã sau khi sửa:
int oddeven (unsigned int x){
int b;
for(b=0; x!=0; x>>=2)
b += ((x & 1) ^ ((x & 2)>>1));
return b;
}
Câu 4 (0.75đ): Tính giá trị các phần tử của mảng A:
int A[]={16,23,34,19};
int *p=A; //p=&A[0]
*p+=2; //A[0]+=2 -> A[]={18,23,34,19}
p+=2; //p=A[2] -> A[]={18,23,34,19}
*p ; //p=A[1] -> A[]={18,23,34,19}
*p+=2; //A[1]+=2 -> A[]={18,25,34,19}
Vậy mảng A sau khi thực hiện đoạn mã lệnh là: A[] = {18,25,34,19}
Câu 5 (1.0đ): Tinh chỉnh đoạn mã lệnh và giải thích lí do:
for ( int i = 0 ; i < n ; i++ ) {
if ( x == y*16 )
DoOneThing(i);
else if ( x == y/8 + z/8 )
DoSomeThingElse(i);
else
DoAnotherThing(i);
}
+ Các cấu trúc rẽ nhánh if-else không phụ thuộc vòng lặp for, do đó ta đưa ra ngoài vòng lặp + Biến đổi các biểu thức nhân chia thành phép toán dịch bit để tăng tốc độ
Đoạn lệnh sau khi tinh chỉnh:
int i;
if (x == y<<4) {
for(i=0; i<n; i++)
DoOneThing(i);
}
else if (x == (y+z)>>3) {
for(i=0; i<n; i++)
Trang 4DoSomeThingElse(i);
}
else {
for(i=0; i<n; i++)
DoAnotherThing(i);
}
Câu 6 (0.75đ): Khi thay đổi khai báo:
char MaTran [80][60]
thành char MaTran [80][64]
Ý nghĩa: thay đổi chỉ số cột từ 60 lên 64 để làm tăng tốc độ tính toán địa chỉ mảng Lí do thay đổi:
+ Với mảng, khi tạo chỉ số, với kích thước mảng bằng 2 , phép nhân có thể được
chuyển thành phép dịch bit, do đó sẽ tối ưu về tốc độ truy cập các phần tử mảng
+ Ở đây, ta nhận thấy 60 ~ 64 = 2 Do đó khi truy cập phần tử MaTran [i, j] thì trình biên dịch
sẽ thay phép toán i*64+j bằng phép toán (i << 6) + j, nhanh hơn
Câu 7 (0.75đ): Cải tiến đoạn mã lệnh sau:
for(int i=0;i<10;i++){
printf(“%f\n”,i*2*sin(b)); //b là hằng số
}
+ Đưa biểu thức bất biến (sin(b)) ra khỏi vòng lặp for
+ Mỗi vòng lặp ta nhân với 2 lần i, do đó thay đổi mỗi lần i tăng 2 đơn vị
Đoạn mã sau khi cải tiến:
float M=sin(b);
for(int i=0;i<20;i+=2){
printf(“%f\n”,i*M);
}
Câu 9 (2đ): Xây dựng hàm sort danh sách LKĐ theo thứ tự giảm dần của info:
void sortDescending(node *head){
int temp;
for(node *p=head; p!=NULL; p=p->next)
for(node *q=p->next; q!=NULL; q=q->next)
if (p->data < q->data) {
temp = p->data;
p->data = q->data;
q->data = temp;
}
cout<<endl<<"Day sau khi sap xep giam la: ";
for(node *p=head; p!=NULL; p=p->next)
cout<<endl<<p->data;
}