Hướng dẫn giải của Sinh vật đơn bào


Chỉ dùng lời giải này khi không có ý tưởng, và đừng copy-paste code từ lời giải này. Hãy tôn trọng người ra đề và người viết lời giải.
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.

Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.

Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.

Bạn phải đăng nhập để mở lời giải này.

Đăng nhập

Tác giả: Hiếu Nguyễn, kienylvp, rubycool9211, oqtn75

Hiểu bài toán

Bài toán yêu cầu tính kết quả của phép nhân một số lớn (đại diện bằng chuỗi ký tự số) với số 2, lặp lại t lần. Ban đầu, ta có một số nguyên lớn S (dưới dạng chuỗi) và một số nguyên dương t. Sau mỗi lần lặp, S được nhân với 2. Cần in ra kết quả cuối cùng sau t lần nhân. Ví dụ, nếu S = "12" và t = 2, kết quả là 12 * 2 * 2 = 48. Do S có thể rất lớn, không thể lưu trữ trong các kiểu dữ liệu nguyên cơ bản mà cần xử lý dưới dạng chuỗi.

Các cách tiếp cận

Cách Nhân lớn với số nguyên nhỏ (tối ưu)
#include <iostream>
#include <string>
using namespace std;

string nhan2(string s) {
    string tmp = "";
    int so_nho = 0;
    for(int i = s.size()-1; i >= 0; i--) {
        int temp = (int(s[i]) - 48) * 2 + so_nho;
        tmp = to_string(temp % 10) + tmp;
        so_nho = temp / 10;
    }
    if (so_nho > 0) tmp = to_string(so_nho) + tmp;
    return tmp;
}

int main() {
    string s;
    int t;
    cin >> s >> t;
    if(s == "0") {
        cout << 0;
        return 0;
    }
    for(int i = 0; i < t; i++) {
        s = nhan2(s);
    }
    cout << s;
    return 0;
}
  • Time Complexity: O(N * t)
  • Space Complexity: O(N)

Đây là cách tiếp cận trực quan nhất để giải quyết bài toán. Nó tận dụng việc chỉ nhân với số 2, phép toán cơ bản. Với mỗi lần nhân, ta duyệt từ chữ số cuối lên chữ số đầu của chuỗi, thực hiện nhân từng chữ số với 2 và cộng với phần nhớ (carry) từ phép tính trước đó. Nếu có phần nhớ cuối cùng, ta thêm nó vào đầu chuỗi. Do độ dài chuỗi tăng chậm (tối đa khoảng N + log2(t) chữ số), độ phức tạp thời gian là O(N * t), đủ nhanh cho các dữ liệu thi đấu thông thường (N, t nhỏ, ví dụ N <= 1000, t <= 1000).

Cách Nhân lớn với số lớn (General)
#include <iostream>
#include <vector>
#include <string>
using namespace std;

string nhan(string s, string n) {
    int len1 = s.size(), len2 = n.size();
    vector<int> res(len1 + len2, 0);

    for (int i = len1 - 1; i >= 0; i--)
        for (int j = len2 - 1; j >= 0; j--)
            res[i + j + 1] += (s[i] - '0') * (n[j] - '0');

    for (int i = len1 + len2 - 1; i > 0; i--) {
        res[i - 1] += res[i] / 10;
        res[i] %= 10;
    }

    string kq;
    int i = 0;
    while (i < res.size() && res[i] == 0) i++;
    if (i == res.size()) return "0";
    for (; i < res.size(); i++) kq.push_back(res[i] + '0');
    return kq;
}

int main() {
    string s, t_str;
    cin >> s >> t_str;
    // Vòng lặp t lần hoặc nhanh hơn nếu t là số
    // Code mẫu này chỉ minh họa hàm nhân chung
    // Trong bài này có thể thay t_str bằng "2" và lặp lại
    return 0;
}
  • Time Complexity: O(N^2 * t)
  • Space Complexity: O(N)

Đây là cách lập trình tổng quát cho phép nhân hai số lớn, sử dụng mảng phụ để lưu kết quả từng cột. Mỗi phép nhân thực hiện phép nhân từng chữ số (thuật toán cơ bản của lớp 3). Trong bài toán này, ta lặp lại phép nhân này t lần. Tuy nhiên, do chỉ nhân với số 2, cách này hơi cồng kềnh và chậm hơn so với cách tối ưu cho số 2 (Approach 1). Độ phức tạp O(N^2 * t) là hơi cao nếu dùng cho việc nhân 2 lặp lại.

Phân tích độ phức tạp

Cách tiếp cận Time Space Tên
1 O(N * t) O(N) Nhân lớn với số nguyên nhỏ (tối ưu)
2 O(N^2 * t) O(N) Nhân lớn với số lớn (General)

Bài học kinh nghiệm

  • Bài toán này về cơ bản là tính 2^t * S.
  • Vì số lượng lần nhân t có thể lớn, nhưng độ dài số tăng chậm, cách nhân trực tiếp từng bước là khả thi.
  • Chuỗi ký tự là cấu trúc dữ liệu duy nhất có thể chứa số rất lớn.

Lỗi thường gặp

  • Sử dụng các kiểu dữ liệu số nguyên (int, long long) để lưu số ban đầu hoặc kết quả trung gian => Bị tràn số (overflow).
  • Lỗi logic khi tính toán nhớ (carry) dẫn đến kết quả sai.
  • Xử lý sai trường hợp input số ban đầu là 0.

Bình luận

Please read the guidelines before commenting.


Không có bình luận tại thời điểm này.