Các lượt nộp
    Danh sách bài
    Trang chủ
    Báo lỗi

    solution

    Đề bài: [Trình biên dịch] Giảm cường độ toán tử cho biến dẫn xuất trong vòng lặp

    Một chương trình có LLL vòng lặp độc lập (không lồng nhau). Vòng lặp thứ kkk chạy đúng NkN_kNk​ lần lặp, đánh số j=0,1,…,Nk−1j = 0, 1, \ldots, N_k-1j=0,1,…,Nk​−1; biến chỉ số vòng lặp iii được khởi tạo i=i0ki = i0_ki=i0k​ trước vòng lặp và tăng thêm stepkstep_kstepk​ mỗi lần lặp, tức tại lần lặp thứ jjj ta có i=i0k+j⋅stepki = i0_k + j \cdot step_ki=i0k​+j⋅stepk​. Trong vòng lặp có VkV_kVk​ biến dẫn xuất (induction variable phụ) u1,…,uVku_1, \ldots, u_{V_k}u1​,…,uVk​​; theo cách tính CHƯA tối ưu, mỗi lần lặp biến utu_tut​ được tính lại từ đầu bằng một phép NHÂN: ut=ct⋅i+dtu_t = c_t \cdot i + d_tut​=ct​⋅i+dt​ (ct,dtc_t, d_tct​,dt​ cho trước).

    Phép biến đổi giảm cường độ toán tử (strength reduction) thay việc tính lại utu_tut​ bằng nhân, bởi: chỉ tính MỘT LẦN giá trị khởi tạo ut(0)=ct⋅i0k+dtu_t^{(0)} = c_t \cdot i0_k + d_tut(0)​=ct​⋅i0k​+dt​ và lượng gia tăng cố định ct⋅stepkc_t \cdot step_kct​⋅stepk​ trước khi vào vòng lặp (các phép nhân này KHÔNG tính là phép nhân "bên trong" vòng lặp), sau đó mỗi lần lặp j≥1j \ge 1j≥1 chỉ cần một phép CỘNG: ut(j)=ut(j−1)+ct⋅stepku_t^{(j)} = u_t^{(j-1)} + c_t \cdot step_kut(j)​=ut(j−1)​+ct​⋅stepk​.

    Với mỗi vòng lặp kkk, hãy tính:

    (a) Tổng số phép NHÂN thực hiện bên trong vòng lặp theo cách CHƯA tối ưu: Nk×VkN_k \times V_kNk​×Vk​.

    (b) Tổng số phép NHÂN thực hiện bên trong vòng lặp SAU KHI giảm cường độ toán tử: luôn bằng 000.

    (c) Giá trị của tất cả các biến dẫn xuất u1,…,uVku_1, \ldots, u_{V_k}u1​,…,uVk​​ ở LẦN LẶP CUỐI CÙNG (j=Nk−1j = N_k - 1j=Nk​−1); nếu Nk=0N_k = 0Nk​=0 (vòng lặp không chạy lần nào) thì không có giá trị nào, in NONE.

    Cuối cùng, in tổng số phép nhân tiết kiệm được trên TOÀN CHƯƠNG TRÌNH (tổng của (a) trừ tổng của (b) qua mọi vòng lặp — vì (b) luôn 0 nên bằng tổng của (a)).

    Lưu ý: dù Nk=0N_k = 0Nk​=0, các biểu thức khởi tạo ut(0)u_t^{(0)}ut(0)​ và lượng gia tăng ct⋅stepkc_t \cdot step_kct​⋅stepk​ vẫn được tính (đây là chi phí NGOÀI vòng lặp, không tính trong (a) hay (b)).

    • Định dạng đầu vào:

      Dòng 1: số nguyên LLL (0≤L≤2000 \le L \le 2000≤L≤200). Với mỗi vòng lặp (k=1..Lk=1..Lk=1..L): một dòng "NkN_kNk​ i0ki0_ki0k​ stepkstep_kstepk​ VkV_kVk​" (0≤Nk≤1060 \le N_k \le 10^60≤Nk​≤106, 0≤Vk≤200 \le V_k \le 200≤Vk​≤20, các số còn lại là số nguyên có thể âm, trị tuyệt đối không vượt 10410^4104), rồi VkV_kVk​ dòng, mỗi dòng "ctc_tct​ dtd_tdt​".

    • Định dạng đầu ra:

      Với mỗi vòng lặp theo đúng thứ tự: một dòng "aaa bbb" (kết quả câu (a), (b)), rồi một dòng cho câu (c) — hoặc NONE (nếu Nk=0N_k=0Nk​=0), hoặc chuỗi VkV_kVk​ giá trị u1,…,uVku_1,\ldots,u_{V_k}u1​,…,uVk​​ cách nhau bởi khoảng trắng (dòng trống nếu Vk=0V_k=0Vk​=0 và Nk>0N_k>0Nk​>0). Sau tất cả các vòng lặp, in một dòng cuối "TOTAL_SAVED sss" với sss là tổng số phép nhân tiết kiệm được.

    Ví dụ:

    Đầu vào:

    2
    5 0 2 2
    3 1
    2 0
    0 10 1 1
    5 5
    

    Đầu ra:

    10 0
    25 16
    0 0
    NONE
    TOTAL_SAVED 10
    

    Đầu vào:

    0
    

    Đầu ra:

    TOTAL_SAVED 0
    

    Đang tải editor...