Bài này mình ra đề cho VNOI Marathon 2013 :D. Hôm nay lục lại máy thấy solution mình viết nên đăng lại lên forum :D

Kiến thức cần biết:

  • Các hàm lượng giác cơ bản

  • Interval tree hoặc Splay tree

  • Maclaurin series / Taylor expansion

 

Các cách giải:

  • 20% test đầu tiên (N, Q <= 5000).

    • Với N và Q nhỏ, cách làm chỉ đơn giản là brute force.

    • Mỗi truy vấn Modify có thể thực hiện trong O(1).

    • Mul, Sin, Cos và Reverse có thể thực hiện trong O(N).

  • 20% test tiếp theo: (ko có Mul & Reverse)

    • Nhận xét:

      • sin(a + b) = sina*cosb + cosa*sinb

    • Như vậy, việc tính tổng sin(Ai + x) có thể dễ dàng được thực hiện nếu ta tính nhanh được tổng sin(Ai). --> có thể dùng interval tree cơ bản để xử lý.

  • 20% test tiếp theo: (ko có Reverse)

    • Để giải quyết được truy vấn dạng Mul, các bạn cần phải biết về Taylor Expansion, hoặc 1 trường hợp đơn giản hơn của nó là Maclaurin Series. https://en.wikipedia.org/wiki/Taylor_series#List_of_Maclaurin_series_of_some_common_functions

    • Từ đó có được công thức xấp xỉ để tính sin (tương tự cho cos) :

      • sin(x) = x - x^3/3! + x^5/5! - x^7/7! + …

    • Với sai số yêu cầu của bài toán, bạn chỉ cần tính khoảng 20 - 30 giá trị đầu.

    • Vì không có thao tác dạng Reverse, bạn chỉ cần một interval tree, lưu lại tổng x^k với mọi k <= 20. Từ đó có thể nhanh chóng tính được tổng trên.

  • 20% test tiếp theo: (ko có Mul)

    • Cách làm giống như 20% thứ 2, nhưng bạn phải cài đặt Splay Tree cho thao tác Reverse.

  • 20% cuối cùng:

    • Kết hợp Splay Tree & Maclaurin Series.